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 <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
35#include <algorithm>
36#include <cctype> // for isspace
37#include <cstdlib> // for malloc, free
38#include <cstring> // for memset
39#include <exception>
40#include <iostream>
41#include <type_traits>
42#include <unordered_map>
43
44namespace {
45
46static const std::unordered_map<std::string_view, std::string_view> typeTranslationMap{
47 {"Bool_t", "bool"},
48 {"Float_t", "float"},
49 {"Double_t", "double"},
50 {"string", "std::string"},
51
52 {"Char_t", "char"},
53 {"int8_t", "std::int8_t"},
54 {"signed char", "char"},
55 {"UChar_t", "std::uint8_t"},
56 {"unsigned char", "std::uint8_t"},
57 {"uint8_t", "std::uint8_t"},
58
59 {"Short_t", "std::int16_t"},
60 {"int16_t", "std::int16_t"},
61 {"short", "std::int16_t"},
62 {"UShort_t", "std::uint16_t"},
63 {"unsigned short", "std::uint16_t"},
64 {"uint16_t", "std::uint16_t"},
65
66 {"Int_t", "std::int32_t"},
67 {"int32_t", "std::int32_t"},
68 {"int", "std::int32_t"},
69 {"UInt_t", "std::uint32_t"},
70 {"unsigned", "std::uint32_t"},
71 {"unsigned int", "std::uint32_t"},
72 {"uint32_t", "std::uint32_t"},
73
74 {"Long_t", "std::int64_t"},
75 {"Long64_t", "std::int64_t"},
76 {"int64_t", "std::int64_t"},
77 {"long", "std::int64_t"},
78 {"ULong64_t", "std::uint64_t"},
79 {"unsigned long", "std::uint64_t"},
80 {"uint64_t", "std::uint64_t"}
81};
82
83/// Used in CreateField() in order to get the comma-separated list of template types
84/// E.g., gets {"int", "std::variant<double,int>"} from "int,std::variant<double,int>"
85std::vector<std::string> TokenizeTypeList(std::string templateType) {
86 std::vector<std::string> result;
87 if (templateType.empty())
88 return result;
89
90 const char *eol = templateType.data() + templateType.length();
91 const char *typeBegin = templateType.data();
92 const char *typeCursor = templateType.data();
93 unsigned int nestingLevel = 0;
94 while (typeCursor != eol) {
95 switch (*typeCursor) {
96 case '<':
97 ++nestingLevel;
98 break;
99 case '>':
100 --nestingLevel;
101 break;
102 case ',':
103 if (nestingLevel == 0) {
104 result.push_back(std::string(typeBegin, typeCursor - typeBegin));
105 typeBegin = typeCursor + 1;
106 }
107 break;
108 }
109 typeCursor++;
110 }
111 result.push_back(std::string(typeBegin, typeCursor - typeBegin));
112 return result;
113}
114
115std::string GetNormalizedType(const std::string &typeName) {
116 std::string normalizedType(
118 /*mode=*/2).c_str()));
119
120 auto translatedType = typeTranslationMap.find(normalizedType);
121 if (translatedType != typeTranslationMap.end())
122 normalizedType = translatedType->second;
123
124 if (normalizedType.substr(0, 7) == "vector<") normalizedType = "std::" + normalizedType;
125 if (normalizedType.substr(0, 6) == "array<") normalizedType = "std::" + normalizedType;
126 if (normalizedType.substr(0, 8) == "variant<") normalizedType = "std::" + normalizedType;
127
128 return normalizedType;
129}
130
131} // anonymous namespace
132
133
134//------------------------------------------------------------------------------
135
136
138 std::string_view name, std::string_view type, ENTupleStructure structure, bool isSimple, std::size_t nRepetitions)
139 : fName(name), fType(type), fStructure(structure), fNRepetitions(nRepetitions), fIsSimple(isSimple),
140 fParent(nullptr), fPrincipalColumn(nullptr)
141{
142}
143
145{
146}
147
149ROOT::Experimental::Detail::RFieldBase::Create(const std::string &fieldName, const std::string &typeName)
150{
151 std::string normalizedType(GetNormalizedType(typeName));
152 if (normalizedType.empty())
153 return R__FAIL("no type name specified for Field " + fieldName);
154
155 std::unique_ptr<ROOT::Experimental::Detail::RFieldBase> result;
156
157 if (normalizedType == "ROOT::Experimental::ClusterSize_t") {
158 result = std::make_unique<RField<ClusterSize_t>>(fieldName);
159 } else if (normalizedType == "bool") {
160 result = std::make_unique<RField<bool>>(fieldName);
161 } else if (normalizedType == "char") {
162 result = std::make_unique<RField<char>>(fieldName);
163 } else if (normalizedType == "std::int8_t") {
164 result = std::make_unique<RField<std::int8_t>>(fieldName);
165 } else if (normalizedType == "std::uint8_t") {
166 result = std::make_unique<RField<std::uint8_t>>(fieldName);
167 } else if (normalizedType == "std::int16_t") {
168 result = std::make_unique<RField<std::int16_t>>(fieldName);
169 } else if (normalizedType == "std::uint16_t") {
170 result = std::make_unique<RField<std::uint16_t>>(fieldName);
171 } else if (normalizedType == "std::int32_t") {
172 result = std::make_unique<RField<std::int32_t>>(fieldName);
173 } else if (normalizedType == "std::uint32_t") {
174 result = std::make_unique<RField<std::uint32_t>>(fieldName);
175 } else if (normalizedType == "std::int64_t") {
176 result = std::make_unique<RField<std::int64_t>>(fieldName);
177 } else if (normalizedType == "std::uint64_t") {
178 result = std::make_unique<RField<std::uint64_t>>(fieldName);
179 } else if (normalizedType == "float") {
180 result = std::make_unique<RField<float>>(fieldName);
181 } else if (normalizedType == "double") {
182 result = std::make_unique<RField<double>>(fieldName);
183 } else if (normalizedType == "std::string") {
184 result = std::make_unique<RField<std::string>>(fieldName);
185 } else if (normalizedType == "std::vector<bool>") {
186 result = std::make_unique<RField<std::vector<bool>>>(fieldName);
187 } else if (normalizedType.substr(0, 12) == "std::vector<") {
188 std::string itemTypeName = normalizedType.substr(12, normalizedType.length() - 13);
189 auto itemField = Create("_0", itemTypeName);
190 result = std::make_unique<RVectorField>(fieldName, itemField.Unwrap());
191 } else if (normalizedType == "ROOT::VecOps::RVec<bool>") {
192 result = std::make_unique<RField<ROOT::VecOps::RVec<bool>>>(fieldName);
193 } else if (normalizedType.substr(0, 19) == "ROOT::VecOps::RVec<") {
194 // For the time being, we silently read RVec fields as std::vector
195 std::string itemTypeName = normalizedType.substr(19, normalizedType.length() - 20);
196 auto itemField = Create("_0", itemTypeName);
197 result = std::make_unique<RVectorField>(fieldName, itemField.Unwrap());
198 } else if (normalizedType.substr(0, 11) == "std::array<") {
199 auto arrayDef = TokenizeTypeList(normalizedType.substr(11, normalizedType.length() - 12));
200 R__ASSERT(arrayDef.size() == 2);
201 auto arrayLength = std::stoi(arrayDef[1]);
202 auto itemField = Create(GetNormalizedType(arrayDef[0]), arrayDef[0]);
203 result = std::make_unique<RArrayField>(fieldName, itemField.Unwrap(), arrayLength);
204 }
205#if __cplusplus >= 201703L
206 if (normalizedType.substr(0, 13) == "std::variant<") {
207 auto innerTypes = TokenizeTypeList(normalizedType.substr(13, normalizedType.length() - 14));
208 std::vector<RFieldBase *> items;
209 for (unsigned int i = 0; i < innerTypes.size(); ++i) {
210 items.emplace_back(Create("_" + std::to_string(i), innerTypes[i]).Unwrap().release());
211 }
212 result = std::make_unique<RVariantField>(fieldName, items);
213 }
214#endif
215 // TODO: create an RCollectionField?
216 if (normalizedType == ":Collection:")
217 result = std::make_unique<RField<ClusterSize_t>>(fieldName);
218
219 if (!result) {
220 auto cl = TClass::GetClass(normalizedType.c_str());
221 if (cl != nullptr) {
222 result = std::make_unique<RClassField>(fieldName, normalizedType);
223 }
224 }
225
226 if (result)
227 return result;
228 return R__FAIL(std::string("Field ") + fieldName + " has unknown type " + normalizedType);
229}
230
233{
234 if (fieldName == "") {
235 return R__FAIL("name cannot be empty string \"\"");
236 } else if (fieldName.find(".") != std::string::npos) {
237 return R__FAIL("name '" + std::string(fieldName) + "' cannot contain dot characters '.'");
238 }
239 return RResult<void>::Success();
240}
241
242std::unique_ptr<ROOT::Experimental::Detail::RFieldBase>
244{
245 auto clone = CloneImpl(newName);
246 clone->fOnDiskId = fOnDiskId;
247 clone->fDescription = fDescription;
248 return clone;
249}
250
252{
253 R__ASSERT(false && "A non-simple RField must implement its own AppendImpl");
254 return 0;
255}
256
259 RFieldValue* /*value*/)
260{
261 R__ASSERT(false);
262}
263
265{
266 void *where = malloc(GetValueSize());
267 R__ASSERT(where != nullptr);
268 return GenerateValue(where);
269}
270
272{
273 if (!dtorOnly)
274 free(value.GetRawPtr());
275}
276
277std::vector<ROOT::Experimental::Detail::RFieldValue>
279{
280 return std::vector<RFieldValue>();
281}
282
284 std::unique_ptr<ROOT::Experimental::Detail::RFieldBase> child)
285{
286 child->fParent = this;
287 fSubFields.emplace_back(std::move(child));
288}
289
290
291std::vector<ROOT::Experimental::Detail::RFieldBase *> ROOT::Experimental::Detail::RFieldBase::GetSubFields() const
292{
293 std::vector<RFieldBase *> result;
294 for (const auto &f : fSubFields) {
295 result.emplace_back(f.get());
296 }
297 return result;
298}
299
300
302{
303 for (auto& column : fColumns) {
304 column->Flush();
305 }
306}
307
308
310 const std::vector<EColumnType> &requestedTypes, unsigned int columnIndex, const RNTupleDescriptor &desc)
311{
312 R__ASSERT(!requestedTypes.empty());
313 auto columnId = desc.FindColumnId(fOnDiskId, columnIndex);
314 if (columnId == kInvalidDescriptorId) {
315 throw RException(R__FAIL("Column missing: column #" + std::to_string(columnIndex) +
316 " for field " + fName));
317 }
318
319 const auto &columnDesc = desc.GetColumnDescriptor(columnId);
320 for (auto type : requestedTypes) {
321 if (type == columnDesc.GetModel().GetType())
322 return type;
323 }
324 throw RException(R__FAIL(
325 "On-disk type `" + RColumnElementBase::GetTypeName(columnDesc.GetModel().GetType()) +
326 "` of column #" + std::to_string(columnIndex) + " for field `" + fName +
327 "` is not convertible to the requested type" + [&]{
328 std::string typeStr = requestedTypes.size() > 1 ? "s " : " ";
329 for (std::size_t i = 0; i < requestedTypes.size(); i++) {
330 typeStr += "`" + RColumnElementBase::GetTypeName(requestedTypes[i]) + "`";
331 if (i != requestedTypes.size() - 1) {
332 typeStr += ", ";
333 }
334 }
335 return typeStr;
336 }()
337 ));
338 return columnDesc.GetModel().GetType();
339}
340
341
343{
344 R__ASSERT(fColumns.empty());
345 GenerateColumnsImpl();
346 if (!fColumns.empty())
347 fPrincipalColumn = fColumns[0].get();
348 for (auto& column : fColumns)
349 column->Connect(fOnDiskId, &pageSink);
350}
351
352
354{
355 R__ASSERT(fColumns.empty());
356 GenerateColumnsImpl(pageSource.GetDescriptor());
357 if (!fColumns.empty())
358 fPrincipalColumn = fColumns[0].get();
359 for (auto& column : fColumns)
360 column->Connect(fOnDiskId, &pageSource);
361}
362
363
365{
366 visitor.VisitField(*this);
367}
368
369
371{
372 if (fSubFields.empty()) return RSchemaIterator(this, -1);
373 return RSchemaIterator(this->fSubFields[0].get(), 0);
374}
375
376
378{
379 return RSchemaIterator(this, -1);
380}
381
382
383//-----------------------------------------------------------------------------
384
385
387{
388 auto itr = fStack.rbegin();
389 if (!itr->fFieldPtr->fSubFields.empty()) {
390 fStack.emplace_back(Position(itr->fFieldPtr->fSubFields[0].get(), 0));
391 return;
392 }
393
394 unsigned int nextIdxInParent = ++(itr->fIdxInParent);
395 while (nextIdxInParent >= itr->fFieldPtr->fParent->fSubFields.size()) {
396 if (fStack.size() == 1) {
397 itr->fFieldPtr = itr->fFieldPtr->fParent;
398 itr->fIdxInParent = -1;
399 return;
400 }
401 fStack.pop_back();
402 itr = fStack.rbegin();
403 nextIdxInParent = ++(itr->fIdxInParent);
404 }
405 itr->fFieldPtr = itr->fFieldPtr->fParent->fSubFields[nextIdxInParent].get();
406}
407
408
409//------------------------------------------------------------------------------
410
411
412std::unique_ptr<ROOT::Experimental::Detail::RFieldBase>
413ROOT::Experimental::RFieldZero::CloneImpl(std::string_view /*newName*/) const
414{
415 auto result = std::make_unique<RFieldZero>();
416 for (auto &f : fSubFields)
417 result->Attach(f->Clone(f->GetName()));
418 return result;
419}
420
421
422std::unique_ptr<ROOT::Experimental::REntry> ROOT::Experimental::RFieldZero::GenerateEntry() const
423{
424 auto entry = std::make_unique<REntry>();
425 for (auto& f : fSubFields) {
426 entry->AddValue(f->GenerateValue());
427 }
428 return entry;
429}
430
432{
433 visitor.VisitFieldZero(*this);
434}
435
436
437//------------------------------------------------------------------------------
438
439
441{
442 RColumnModel model(EColumnType::kIndex, true /* isSorted*/);
443 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(
444 Detail::RColumn::Create<ClusterSize_t, EColumnType::kIndex>(model, 0)));
445}
446
448{
449 EnsureColumnType({EColumnType::kIndex}, 0, desc);
450 GenerateColumnsImpl();
451}
452
454{
455 visitor.VisitClusterSizeField(*this);
456}
457
458//------------------------------------------------------------------------------
459
461{
462 RColumnModel model(EColumnType::kChar, false /* isSorted*/);
463 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(Detail::RColumn::Create<
464 char, EColumnType::kChar>(model, 0)));
465}
466
468{
469 EnsureColumnType({EColumnType::kChar}, 0, desc);
470 GenerateColumnsImpl();
471}
472
474{
475 visitor.VisitCharField(*this);
476}
477
478//------------------------------------------------------------------------------
479
481{
482 RColumnModel model(EColumnType::kInt8, false /* isSorted*/);
483 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(Detail::RColumn::Create<
484 std::int8_t, EColumnType::kInt8>(model, 0)));
485}
486
487void ROOT::Experimental::RField<std::int8_t>::GenerateColumnsImpl(const RNTupleDescriptor &desc)
488{
489 EnsureColumnType({EColumnType::kInt8}, 0, desc);
490 GenerateColumnsImpl();
491}
492
493void ROOT::Experimental::RField<std::int8_t>::AcceptVisitor(Detail::RFieldVisitor &visitor) const
494{
495 visitor.VisitInt8Field(*this);
496}
497
498//------------------------------------------------------------------------------
499
501{
502 RColumnModel model(EColumnType::kInt8, false /* isSorted*/);
503 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(Detail::RColumn::Create<
504 std::uint8_t, EColumnType::kInt8>(model, 0)));
505}
506
508{
509 EnsureColumnType({EColumnType::kInt8}, 0, desc);
510 GenerateColumnsImpl();
511}
512
513void ROOT::Experimental::RField<std::uint8_t>::AcceptVisitor(Detail::RFieldVisitor &visitor) const
514{
515 visitor.VisitUInt8Field(*this);
516}
517
518//------------------------------------------------------------------------------
519
520
522{
523 RColumnModel model(EColumnType::kBit, false /* isSorted*/);
524 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(
525 Detail::RColumn::Create<bool, EColumnType::kBit>(model, 0)));
526}
527
529{
530 EnsureColumnType({EColumnType::kBit}, 0, desc);
531 GenerateColumnsImpl();
532}
533
535{
536 visitor.VisitBoolField(*this);
537}
538
539//------------------------------------------------------------------------------
540
541
543{
544 RColumnModel model(EColumnType::kReal32, false /* isSorted*/);
545 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(
546 Detail::RColumn::Create<float, EColumnType::kReal32>(model, 0)));
547}
548
550{
551 EnsureColumnType({EColumnType::kReal32}, 0, desc);
552 GenerateColumnsImpl();
553}
554
556{
557 visitor.VisitFloatField(*this);
558}
559
560
561//------------------------------------------------------------------------------
562
564{
565 RColumnModel model(EColumnType::kReal64, false /* isSorted*/);
566 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(
567 Detail::RColumn::Create<double, EColumnType::kReal64>(model, 0)));
568}
569
571{
572 EnsureColumnType({EColumnType::kReal64}, 0, desc);
573 GenerateColumnsImpl();
574}
575
577{
578 visitor.VisitDoubleField(*this);
579}
580
581//------------------------------------------------------------------------------
582
584{
585 RColumnModel model(EColumnType::kInt16, false /* isSorted*/);
586 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(Detail::RColumn::Create<
587 std::int16_t, EColumnType::kInt16>(model, 0)));
588}
589
591{
592 EnsureColumnType({EColumnType::kInt16}, 0, desc);
593 GenerateColumnsImpl();
594}
595
596void ROOT::Experimental::RField<std::int16_t>::AcceptVisitor(Detail::RFieldVisitor &visitor) const
597{
598 visitor.VisitInt16Field(*this);
599}
600
601//------------------------------------------------------------------------------
602
604{
605 RColumnModel model(EColumnType::kInt16, false /* isSorted*/);
606 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(Detail::RColumn::Create<
607 std::uint16_t, EColumnType::kInt16>(model, 0)));
608}
609
611{
612 EnsureColumnType({EColumnType::kInt16}, 0, desc);
613 GenerateColumnsImpl();
614}
615
616void ROOT::Experimental::RField<std::uint16_t>::AcceptVisitor(Detail::RFieldVisitor &visitor) const
617{
618 visitor.VisitUInt16Field(*this);
619}
620
621//------------------------------------------------------------------------------
622
624{
625 RColumnModel model(EColumnType::kInt32, false /* isSorted*/);
626 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(Detail::RColumn::Create<
627 std::int32_t, EColumnType::kInt32>(model, 0)));
628}
629
631{
632 EnsureColumnType({EColumnType::kInt32}, 0, desc);
633 GenerateColumnsImpl();
634}
635
636void ROOT::Experimental::RField<std::int32_t>::AcceptVisitor(Detail::RFieldVisitor &visitor) const
637{
638 visitor.VisitIntField(*this);
639}
640
641//------------------------------------------------------------------------------
642
644{
645 RColumnModel model(EColumnType::kInt32, false /* isSorted*/);
646 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(
647 Detail::RColumn::Create<std::uint32_t, EColumnType::kInt32>(model, 0)));
648}
649
651{
652 EnsureColumnType({EColumnType::kInt32}, 0, desc);
653 GenerateColumnsImpl();
654}
655
656void ROOT::Experimental::RField<std::uint32_t>::AcceptVisitor(Detail::RFieldVisitor &visitor) const
657{
658 visitor.VisitUInt32Field(*this);
659}
660
661//------------------------------------------------------------------------------
662
664{
665 RColumnModel model(EColumnType::kInt64, false /* isSorted*/);
666 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(
667 Detail::RColumn::Create<std::uint64_t, EColumnType::kInt64>(model, 0)));
668}
669
671{
672 EnsureColumnType({EColumnType::kInt64}, 0, desc);
673 GenerateColumnsImpl();
674}
675
676void ROOT::Experimental::RField<std::uint64_t>::AcceptVisitor(Detail::RFieldVisitor &visitor) const
677{
678 visitor.VisitUInt64Field(*this);
679}
680
681//------------------------------------------------------------------------------
682
684{
685 RColumnModel model(EColumnType::kInt64, false /* isSorted*/);
686 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(
687 Detail::RColumn::Create<std::int64_t, EColumnType::kInt64>(model, 0)));
688}
689
691{
692 auto type = EnsureColumnType({EColumnType::kInt64, EColumnType::kInt32}, 0, desc);
693 RColumnModel model(type, false /* isSorted*/);
694 if (type == EColumnType::kInt64) {
695 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(
696 Detail::RColumn::Create<std::int64_t, EColumnType::kInt64>(model, 0)));
697 } else {
698 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(
699 Detail::RColumn::Create<std::int64_t, EColumnType::kInt32>(model, 0)));
700 }
701}
702
703void ROOT::Experimental::RField<std::int64_t>::AcceptVisitor(Detail::RFieldVisitor &visitor) const
704{
705 visitor.VisitInt64Field(*this);
706}
707
708//------------------------------------------------------------------------------
709
711{
712 RColumnModel modelIndex(EColumnType::kIndex, true /* isSorted*/);
713 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(
714 Detail::RColumn::Create<ClusterSize_t, EColumnType::kIndex>(modelIndex, 0)));
715
716 RColumnModel modelChars(EColumnType::kChar, false /* isSorted*/);
717 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(
718 Detail::RColumn::Create<char, EColumnType::kChar>(modelChars, 1)));
719}
720
721void ROOT::Experimental::RField<std::string>::GenerateColumnsImpl(const RNTupleDescriptor &desc)
722{
723 EnsureColumnType({EColumnType::kIndex}, 0, desc);
724 EnsureColumnType({EColumnType::kChar}, 1, desc);
725 GenerateColumnsImpl();
726}
727
729{
730 auto typedValue = value.Get<std::string>();
731 auto length = typedValue->length();
732 Detail::RColumnElement<char> elemChars(const_cast<char*>(typedValue->data()));
733 fColumns[1]->AppendV(elemChars, length);
734 fIndex += length;
735 fColumns[0]->Append(fElemIndex);
736 return length + sizeof(fElemIndex);
737}
738
741{
742 auto typedValue = value->Get<std::string>();
743 RClusterIndex collectionStart;
744 ClusterSize_t nChars;
745 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &nChars);
746 if (nChars == 0) {
747 typedValue->clear();
748 } else {
749 typedValue->resize(nChars);
750 Detail::RColumnElement<char> elemChars(const_cast<char*>(typedValue->data()));
751 fColumns[1]->ReadV(collectionStart, nChars, &elemChars);
752 }
753}
754
756{
757 fIndex = 0;
758}
759
760void ROOT::Experimental::RField<std::string>::AcceptVisitor(Detail::RFieldVisitor &visitor) const
761{
762 visitor.VisitStringField(*this);
763}
764
765//------------------------------------------------------------------------------
766
767
768ROOT::Experimental::RClassField::RClassField(std::string_view fieldName, std::string_view className)
769 : RClassField(fieldName, className, TClass::GetClass(std::string(className).c_str()))
770{
771}
772
773ROOT::Experimental::RClassField::RClassField(std::string_view fieldName, std::string_view className, TClass *classp)
774 : ROOT::Experimental::Detail::RFieldBase(fieldName, className, ENTupleStructure::kRecord, false /* isSimple */)
775 , fClass(classp)
776{
777 if (fClass == nullptr) {
778 throw std::runtime_error("RField: no I/O support for type " + std::string(className));
779 }
780 // Avoid accidentally supporting std types through TClass.
782 throw RException(R__FAIL(std::string(className) + " is not supported"));
783 }
784
785 int i = 0;
787 TClass *c = baseClass->GetClassPointer();
788 auto subField = Detail::RFieldBase::Create(std::string(kPrefixInherited) + "_" + std::to_string(i),
789 c->GetName()).Unwrap();
790 Attach(std::move(subField),
791 RSubFieldInfo{kBaseClass, static_cast<std::size_t>(baseClass->GetDelta())});
792 i++;
793 }
795 if (!dataMember->IsPersistent())
796 continue;
797 auto subField = Detail::RFieldBase::Create(dataMember->GetName(), dataMember->GetFullTypeName()).Unwrap();
798 Attach(std::move(subField),
799 RSubFieldInfo{kDataMember, static_cast<std::size_t>(dataMember->GetOffset())});
800 }
801}
802
803void ROOT::Experimental::RClassField::Attach(std::unique_ptr<Detail::RFieldBase> child, RSubFieldInfo info)
804{
805 fMaxAlignment = std::max(fMaxAlignment, child->GetAlignment());
806 fSubFieldsInfo.push_back(info);
807 RFieldBase::Attach(std::move(child));
808}
809
810std::unique_ptr<ROOT::Experimental::Detail::RFieldBase>
811ROOT::Experimental::RClassField::CloneImpl(std::string_view newName) const
812{
813 return std::unique_ptr<RClassField>(new RClassField(newName, GetType(), fClass));
814}
815
817 std::size_t nbytes = 0;
818 for (unsigned i = 0; i < fSubFields.size(); i++) {
819 auto memberValue = fSubFields[i]->CaptureValue(value.Get<unsigned char>() + fSubFieldsInfo[i].fOffset);
820 nbytes += fSubFields[i]->Append(memberValue);
821 }
822 return nbytes;
823}
824
826{
827 for (unsigned i = 0; i < fSubFields.size(); i++) {
828 auto memberValue = fSubFields[i]->CaptureValue(value->Get<unsigned char>() + fSubFieldsInfo[i].fOffset);
829 fSubFields[i]->Read(globalIndex, &memberValue);
830 }
831}
832
834{
835 for (unsigned i = 0; i < fSubFields.size(); i++) {
836 auto memberValue = fSubFields[i]->CaptureValue(value->Get<unsigned char>() + fSubFieldsInfo[i].fOffset);
837 fSubFields[i]->Read(clusterIndex, &memberValue);
838 }
839}
840
842{
843}
844
846{
847}
848
850{
851 return Detail::RFieldValue(true /* captureFlag */, this, fClass->New(where));
852}
853
855{
856 fClass->Destructor(value.GetRawPtr(), true /* dtorOnly */);
857 if (!dtorOnly)
858 free(value.GetRawPtr());
859}
860
862{
863 return Detail::RFieldValue(true /* captureFlat */, this, where);
864}
865
866
867std::vector<ROOT::Experimental::Detail::RFieldValue>
869{
870 std::vector<Detail::RFieldValue> result;
871 for (unsigned i = 0; i < fSubFields.size(); i++) {
872 auto memberValue = fSubFields[i]->CaptureValue(value.Get<unsigned char>() + fSubFieldsInfo[i].fOffset);
873 result.emplace_back(memberValue);
874 }
875 return result;
876}
877
878
880{
881 return fClass->GetClassSize();
882}
883
885{
886 visitor.VisitClassField(*this);
887}
888
889//------------------------------------------------------------------------------
890
892 std::string_view fieldName, std::vector<std::unique_ptr<Detail::RFieldBase>> &itemFields)
893 : ROOT::Experimental::Detail::RFieldBase(fieldName, "", ENTupleStructure::kRecord, false /* isSimple */)
894{
895 for (auto &item : itemFields) {
896 fMaxAlignment = std::max(fMaxAlignment, item->GetAlignment());
897 fSize += GetItemPadding(fSize, item->GetAlignment()) + item->GetValueSize();
898 Attach(std::move(item));
899 }
900}
901
902
903std::size_t ROOT::Experimental::RRecordField::GetItemPadding(std::size_t baseOffset, std::size_t itemAlignment) const
904{
905 if (itemAlignment > 1) {
906 auto remainder = baseOffset % itemAlignment;
907 if (remainder != 0)
908 return itemAlignment - remainder;
909 }
910 return 0;
911}
912
913std::unique_ptr<ROOT::Experimental::Detail::RFieldBase>
914ROOT::Experimental::RRecordField::CloneImpl(std::string_view newName) const
915{
916 std::vector<std::unique_ptr<Detail::RFieldBase>> cloneItems;
917 for (auto &item : fSubFields)
918 cloneItems.emplace_back(item->Clone(item->GetName()));
919 return std::make_unique<RRecordField>(newName, cloneItems);
920}
921
923 std::size_t nbytes = 0;
924 std::size_t offset = 0;
925 for (auto &item : fSubFields) {
926 auto memberValue = item->CaptureValue(value.Get<unsigned char>() + offset);
927 nbytes += item->Append(memberValue);
928 offset += GetItemPadding(offset, item->GetAlignment()) + item->GetValueSize();
929 }
930 return nbytes;
931}
932
934{
935 std::size_t offset = 0;
936 for (auto &item : fSubFields) {
937 auto memberValue = item->CaptureValue(value->Get<unsigned char>() + offset);
938 item->Read(globalIndex, &memberValue);
939 offset += GetItemPadding(offset, item->GetAlignment()) + item->GetValueSize();
940 }
941}
942
944{
945 std::size_t offset = 0;
946 for (auto &item : fSubFields) {
947 auto memberValue = item->CaptureValue(value->Get<unsigned char>() + offset);
948 item->Read(clusterIndex, &memberValue);
949 offset += GetItemPadding(offset, item->GetAlignment()) + item->GetValueSize();
950 }
951}
952
954{
955 std::size_t offset = 0;
956 for (auto &item : fSubFields) {
957 item->GenerateValue(static_cast<unsigned char *>(where) + offset);
958 offset += GetItemPadding(offset, item->GetAlignment()) + item->GetValueSize();
959 }
960 return Detail::RFieldValue(true /* captureFlag */, this, where);
961}
962
964{
965 std::size_t offset = 0;
966 for (auto &item : fSubFields) {
967 auto memberValue = item->CaptureValue(value.Get<unsigned char>() + offset);
968 item->DestroyValue(memberValue, true /* dtorOnly */);
969 offset += GetItemPadding(offset, item->GetAlignment()) + item->GetValueSize();
970 }
971
972 if (!dtorOnly)
973 free(value.GetRawPtr());
974}
975
977{
978 return Detail::RFieldValue(true /* captureFlag */, this, where);
979}
980
981
982std::vector<ROOT::Experimental::Detail::RFieldValue>
984{
985 std::size_t offset = 0;
986 std::vector<Detail::RFieldValue> result;
987 for (auto &item : fSubFields) {
988 result.emplace_back(item->CaptureValue(value.Get<unsigned char>() + offset));
989 offset += GetItemPadding(offset, item->GetAlignment()) + item->GetValueSize();
990 }
991 return result;
992}
993
994
996{
997 visitor.VisitRecordField(*this);
998}
999
1000//------------------------------------------------------------------------------
1001
1002
1004 std::string_view fieldName, std::unique_ptr<Detail::RFieldBase> itemField)
1005 : ROOT::Experimental::Detail::RFieldBase(
1006 fieldName, "std::vector<" + itemField->GetType() + ">", ENTupleStructure::kCollection, false /* isSimple */)
1007 , fItemSize(itemField->GetValueSize()), fNWritten(0)
1008{
1009 Attach(std::move(itemField));
1010}
1011
1012std::unique_ptr<ROOT::Experimental::Detail::RFieldBase>
1013ROOT::Experimental::RVectorField::CloneImpl(std::string_view newName) const
1014{
1015 auto newItemField = fSubFields[0]->Clone(fSubFields[0]->GetName());
1016 return std::make_unique<RVectorField>(newName, std::move(newItemField));
1017}
1018
1020 auto typedValue = value.Get<std::vector<char>>();
1021 R__ASSERT((typedValue->size() % fItemSize) == 0);
1022 std::size_t nbytes = 0;
1023 auto count = typedValue->size() / fItemSize;
1024 for (unsigned i = 0; i < count; ++i) {
1025 auto itemValue = fSubFields[0]->CaptureValue(typedValue->data() + (i * fItemSize));
1026 nbytes += fSubFields[0]->Append(itemValue);
1027 }
1028 Detail::RColumnElement<ClusterSize_t> elemIndex(&fNWritten);
1029 fNWritten += count;
1030 fColumns[0]->Append(elemIndex);
1031 return nbytes + sizeof(elemIndex);
1032}
1033
1035{
1036 auto typedValue = value->Get<std::vector<char>>();
1037
1038 ClusterSize_t nItems;
1039 RClusterIndex collectionStart;
1040 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &nItems);
1041
1042 auto oldNItems = typedValue->size() / fItemSize;
1043 for (std::size_t i = nItems; i < oldNItems; ++i) {
1044 auto itemValue = fSubFields[0]->CaptureValue(typedValue->data() + (i * fItemSize));
1045 fSubFields[0]->DestroyValue(itemValue, true /* dtorOnly */);
1046 }
1047 typedValue->resize(nItems * fItemSize);
1048 for (std::size_t i = oldNItems; i < nItems; ++i) {
1049 fSubFields[0]->GenerateValue(typedValue->data() + (i * fItemSize));
1050 }
1051
1052 for (std::size_t i = 0; i < nItems; ++i) {
1053 auto itemValue = fSubFields[0]->CaptureValue(typedValue->data() + (i * fItemSize));
1054 fSubFields[0]->Read(collectionStart + i, &itemValue);
1055 }
1056}
1057
1059{
1060 RColumnModel modelIndex(EColumnType::kIndex, true /* isSorted*/);
1061 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(
1062 Detail::RColumn::Create<ClusterSize_t, EColumnType::kIndex>(modelIndex, 0)));
1063}
1064
1066{
1067 EnsureColumnType({EColumnType::kIndex}, 0, desc);
1068 GenerateColumnsImpl();
1069}
1070
1072{
1073 return Detail::RFieldValue(this, reinterpret_cast<std::vector<char>*>(where));
1074}
1075
1077{
1078 auto vec = static_cast<std::vector<char>*>(value.GetRawPtr());
1079 R__ASSERT((vec->size() % fItemSize) == 0);
1080 auto nItems = vec->size() / fItemSize;
1081 for (unsigned i = 0; i < nItems; ++i) {
1082 auto itemValue = fSubFields[0]->CaptureValue(vec->data() + (i * fItemSize));
1083 fSubFields[0]->DestroyValue(itemValue, true /* dtorOnly */);
1084 }
1085 vec->~vector();
1086 if (!dtorOnly)
1087 free(vec);
1088}
1089
1091{
1092 return Detail::RFieldValue(true /* captureFlag */, this, where);
1093}
1094
1095std::vector<ROOT::Experimental::Detail::RFieldValue>
1097{
1098 auto vec = static_cast<std::vector<char>*>(value.GetRawPtr());
1099 R__ASSERT((vec->size() % fItemSize) == 0);
1100 auto nItems = vec->size() / fItemSize;
1101 std::vector<Detail::RFieldValue> result;
1102 for (unsigned i = 0; i < nItems; ++i) {
1103 result.emplace_back(fSubFields[0]->CaptureValue(vec->data() + (i * fItemSize)));
1104 }
1105 return result;
1106}
1107
1109{
1110 fNWritten = 0;
1111}
1112
1114{
1115 visitor.VisitVectorField(*this);
1116}
1117
1118
1119//------------------------------------------------------------------------------
1120
1121
1123 : ROOT::Experimental::Detail::RFieldBase(name, "std::vector<bool>", ENTupleStructure::kCollection,
1124 false /* isSimple */)
1125{
1126 Attach(std::make_unique<RField<bool>>("_0"));
1127}
1128
1129std::size_t ROOT::Experimental::RField<std::vector<bool>>::AppendImpl(const Detail::RFieldValue& value) {
1130 auto typedValue = value.Get<std::vector<bool>>();
1131 auto count = typedValue->size();
1132 for (unsigned i = 0; i < count; ++i) {
1133 bool bval = (*typedValue)[i];
1134 auto itemValue = fSubFields[0]->CaptureValue(&bval);
1135 fSubFields[0]->Append(itemValue);
1136 }
1137 Detail::RColumnElement<ClusterSize_t> elemIndex(&fNWritten);
1138 fNWritten += count;
1139 fColumns[0]->Append(elemIndex);
1140 return count + sizeof(elemIndex);
1141}
1142
1143void ROOT::Experimental::RField<std::vector<bool>>::ReadGlobalImpl(NTupleSize_t globalIndex, Detail::RFieldValue* value)
1144{
1145 auto typedValue = value->Get<std::vector<bool>>();
1146
1147 ClusterSize_t nItems;
1148 RClusterIndex collectionStart;
1149 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &nItems);
1150
1151 typedValue->resize(nItems);
1152 for (unsigned i = 0; i < nItems; ++i) {
1153 bool bval;
1154 auto itemValue = fSubFields[0]->GenerateValue(&bval);
1155 fSubFields[0]->Read(collectionStart + i, &itemValue);
1156 (*typedValue)[i] = bval;
1157 }
1158}
1159
1160void ROOT::Experimental::RField<std::vector<bool>>::GenerateColumnsImpl()
1161{
1162 RColumnModel modelIndex(EColumnType::kIndex, true /* isSorted*/);
1163 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(
1164 Detail::RColumn::Create<ClusterSize_t, EColumnType::kIndex>(modelIndex, 0)));
1165}
1166
1167void ROOT::Experimental::RField<std::vector<bool>>::GenerateColumnsImpl(const RNTupleDescriptor &desc)
1168{
1169 EnsureColumnType({EColumnType::kIndex}, 0, desc);
1170 GenerateColumnsImpl();
1171}
1172
1173std::vector<ROOT::Experimental::Detail::RFieldValue>
1174ROOT::Experimental::RField<std::vector<bool>>::SplitValue(const Detail::RFieldValue& value) const
1175{
1176 const static bool trueValue = true;
1177 const static bool falseValue = false;
1178
1179 auto typedValue = value.Get<std::vector<bool>>();
1180 auto count = typedValue->size();
1181 std::vector<Detail::RFieldValue> result;
1182 for (unsigned i = 0; i < count; ++i) {
1183 if ((*typedValue)[i])
1184 result.emplace_back(fSubFields[0]->CaptureValue(const_cast<bool *>(&trueValue)));
1185 else
1186 result.emplace_back(fSubFields[0]->CaptureValue(const_cast<bool *>(&falseValue)));
1187 }
1188 return result;
1189}
1190
1191
1192void ROOT::Experimental::RField<std::vector<bool>>::DestroyValue(const Detail::RFieldValue& value, bool dtorOnly)
1193{
1194 auto vec = static_cast<std::vector<bool>*>(value.GetRawPtr());
1195 vec->~vector();
1196 if (!dtorOnly)
1197 free(vec);
1198}
1199
1200void ROOT::Experimental::RField<std::vector<bool>>::AcceptVisitor(Detail::RFieldVisitor &visitor) const
1201{
1202 visitor.VisitVectorBoolField(*this);
1203}
1204
1205
1206//------------------------------------------------------------------------------
1207
1208
1210 std::string_view fieldName, std::unique_ptr<Detail::RFieldBase> itemField, std::size_t arrayLength)
1211 : ROOT::Experimental::Detail::RFieldBase(
1212 fieldName, "std::array<" + itemField->GetType() + "," + std::to_string(arrayLength) + ">",
1213 ENTupleStructure::kLeaf, false /* isSimple */, arrayLength)
1214 , fItemSize(itemField->GetValueSize()), fArrayLength(arrayLength)
1215{
1216 Attach(std::move(itemField));
1217}
1218
1219std::unique_ptr<ROOT::Experimental::Detail::RFieldBase>
1220ROOT::Experimental::RArrayField::CloneImpl(std::string_view newName) const
1221{
1222 auto newItemField = fSubFields[0]->Clone(fSubFields[0]->GetName());
1223 return std::make_unique<RArrayField>(newName, std::move(newItemField), fArrayLength);
1224}
1225
1227 std::size_t nbytes = 0;
1228 auto arrayPtr = value.Get<unsigned char>();
1229 for (unsigned i = 0; i < fArrayLength; ++i) {
1230 auto itemValue = fSubFields[0]->CaptureValue(arrayPtr + (i * fItemSize));
1231 nbytes += fSubFields[0]->Append(itemValue);
1232 }
1233 return nbytes;
1234}
1235
1237{
1238 auto arrayPtr = value->Get<unsigned char>();
1239 for (unsigned i = 0; i < fArrayLength; ++i) {
1240 auto itemValue = fSubFields[0]->GenerateValue(arrayPtr + (i * fItemSize));
1241 fSubFields[0]->Read(globalIndex * fArrayLength + i, &itemValue);
1242 }
1243}
1244
1246{
1247 auto arrayPtr = value->Get<unsigned char>();
1248 for (unsigned i = 0; i < fArrayLength; ++i) {
1249 auto itemValue = fSubFields[0]->GenerateValue(arrayPtr + (i * fItemSize));
1250 fSubFields[0]->Read(RClusterIndex(clusterIndex.GetClusterId(), clusterIndex.GetIndex() * fArrayLength + i),
1251 &itemValue);
1252 }
1253}
1254
1256{
1257}
1258
1260{
1261}
1262
1264{
1265 auto arrayPtr = reinterpret_cast<unsigned char *>(where);
1266 for (unsigned i = 0; i < fArrayLength; ++i) {
1267 fSubFields[0]->GenerateValue(arrayPtr + (i * fItemSize));
1268 }
1269 return Detail::RFieldValue(true /* captureFlag */, this, where);
1270}
1271
1273{
1274 auto arrayPtr = value.Get<unsigned char>();
1275 for (unsigned i = 0; i < fArrayLength; ++i) {
1276 auto itemValue = fSubFields[0]->CaptureValue(arrayPtr + (i * fItemSize));
1277 fSubFields[0]->DestroyValue(itemValue, true /* dtorOnly */);
1278 }
1279 if (!dtorOnly)
1280 free(arrayPtr);
1281}
1282
1284{
1285 return Detail::RFieldValue(true /* captureFlag */, this, where);
1286}
1287
1288std::vector<ROOT::Experimental::Detail::RFieldValue>
1290{
1291 auto arrayPtr = value.Get<unsigned char>();
1292 std::vector<Detail::RFieldValue> result;
1293 for (unsigned i = 0; i < fArrayLength; ++i) {
1294 auto itemValue = fSubFields[0]->CaptureValue(arrayPtr + (i * fItemSize));
1295 result.emplace_back(itemValue);
1296 }
1297 return result;
1298}
1299
1301{
1302 visitor.VisitArrayField(*this);
1303}
1304
1305//------------------------------------------------------------------------------
1306
1307#if __cplusplus >= 201703L
1308std::string ROOT::Experimental::RVariantField::GetTypeList(const std::vector<Detail::RFieldBase *> &itemFields)
1309{
1310 std::string result;
1311 for (size_t i = 0; i < itemFields.size(); ++i) {
1312 result += itemFields[i]->GetType() + ",";
1313 }
1314 R__ASSERT(!result.empty()); // there is always at least one variant
1315 result.pop_back(); // remove trailing comma
1316 return result;
1317}
1318
1319ROOT::Experimental::RVariantField::RVariantField(
1320 std::string_view fieldName, const std::vector<Detail::RFieldBase *> &itemFields)
1321 : ROOT::Experimental::Detail::RFieldBase(fieldName,
1322 "std::variant<" + GetTypeList(itemFields) + ">", ENTupleStructure::kVariant, false /* isSimple */)
1323{
1324 auto nFields = itemFields.size();
1325 R__ASSERT(nFields > 0);
1326 fNWritten.resize(nFields, 0);
1327 for (unsigned int i = 0; i < nFields; ++i) {
1328 fMaxItemSize = std::max(fMaxItemSize, itemFields[i]->GetValueSize());
1329 fMaxAlignment = std::max(fMaxAlignment, itemFields[i]->GetAlignment());
1330 Attach(std::unique_ptr<Detail::RFieldBase>(itemFields[i]));
1331 }
1332 fTagOffset = (fMaxItemSize < fMaxAlignment) ? fMaxAlignment : fMaxItemSize;
1333}
1334
1335std::unique_ptr<ROOT::Experimental::Detail::RFieldBase>
1336ROOT::Experimental::RVariantField::CloneImpl(std::string_view newName) const
1337{
1338 auto nFields = fSubFields.size();
1339 std::vector<Detail::RFieldBase *> itemFields;
1340 for (unsigned i = 0; i < nFields; ++i) {
1341 // TODO(jblomer): use unique_ptr in RVariantField constructor
1342 itemFields.emplace_back(fSubFields[i]->Clone(fSubFields[i]->GetName()).release());
1343 }
1344 return std::make_unique<RVariantField>(newName, itemFields);
1345}
1346
1347std::uint32_t ROOT::Experimental::RVariantField::GetTag(void *variantPtr) const
1348{
1349 auto index = *(reinterpret_cast<char *>(variantPtr) + fTagOffset);
1350 return (index < 0) ? 0 : index + 1;
1351}
1352
1353void ROOT::Experimental::RVariantField::SetTag(void *variantPtr, std::uint32_t tag) const
1354{
1355 auto index = reinterpret_cast<char *>(variantPtr) + fTagOffset;
1356 *index = static_cast<char>(tag - 1);
1357}
1358
1359std::size_t ROOT::Experimental::RVariantField::AppendImpl(const Detail::RFieldValue& value)
1360{
1361 auto tag = GetTag(value.GetRawPtr());
1362 std::size_t nbytes = 0;
1363 auto index = 0;
1364 if (tag > 0) {
1365 auto itemValue = fSubFields[tag - 1]->CaptureValue(value.GetRawPtr());
1366 nbytes += fSubFields[tag - 1]->Append(itemValue);
1367 index = fNWritten[tag - 1]++;
1368 }
1369 RColumnSwitch varSwitch(ClusterSize_t(index), tag);
1370 Detail::RColumnElement<RColumnSwitch> elemSwitch(&varSwitch);
1371 fColumns[0]->Append(elemSwitch);
1372 return nbytes + sizeof(RColumnSwitch);
1373}
1374
1375void ROOT::Experimental::RVariantField::ReadGlobalImpl(NTupleSize_t globalIndex, Detail::RFieldValue *value)
1376{
1377 RClusterIndex variantIndex;
1378 std::uint32_t tag;
1379 fPrincipalColumn->GetSwitchInfo(globalIndex, &variantIndex, &tag);
1380 R__ASSERT(tag > 0); // TODO(jblomer): deal with invalid variants
1381
1382 auto itemValue = fSubFields[tag - 1]->GenerateValue(value->GetRawPtr());
1383 fSubFields[tag - 1]->Read(variantIndex, &itemValue);
1384 SetTag(value->GetRawPtr(), tag);
1385}
1386
1387void ROOT::Experimental::RVariantField::GenerateColumnsImpl()
1388{
1389 RColumnModel modelSwitch(EColumnType::kSwitch, false);
1390 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(
1391 Detail::RColumn::Create<RColumnSwitch, EColumnType::kSwitch>(modelSwitch, 0)));
1392}
1393
1394void ROOT::Experimental::RVariantField::GenerateColumnsImpl(const RNTupleDescriptor &desc)
1395{
1396 EnsureColumnType({EColumnType::kSwitch}, 0, desc);
1397 GenerateColumnsImpl();
1398}
1399
1400ROOT::Experimental::Detail::RFieldValue ROOT::Experimental::RVariantField::GenerateValue(void *where)
1401{
1402 memset(where, 0, GetValueSize());
1403 fSubFields[0]->GenerateValue(where);
1404 SetTag(where, 1);
1405 return Detail::RFieldValue(this, reinterpret_cast<unsigned char *>(where));
1406}
1407
1408void ROOT::Experimental::RVariantField::DestroyValue(const Detail::RFieldValue& value, bool dtorOnly)
1409{
1410 auto variantPtr = value.GetRawPtr();
1411 auto tag = GetTag(variantPtr);
1412 if (tag > 0) {
1413 auto itemValue = fSubFields[tag - 1]->CaptureValue(variantPtr);
1414 fSubFields[tag - 1]->DestroyValue(itemValue, true /* dtorOnly */);
1415 }
1416 if (!dtorOnly)
1417 free(variantPtr);
1418}
1419
1420ROOT::Experimental::Detail::RFieldValue ROOT::Experimental::RVariantField::CaptureValue(void *where)
1421{
1422 return Detail::RFieldValue(true /* captureFlag */, this, where);
1423}
1424
1425size_t ROOT::Experimental::RVariantField::GetValueSize() const
1426{
1427 return fMaxItemSize + fMaxAlignment; // TODO: fix for more than 255 items
1428}
1429
1430void ROOT::Experimental::RVariantField::CommitCluster()
1431{
1432 std::fill(fNWritten.begin(), fNWritten.end(), 0);
1433}
1434#endif
1435
1436
1437//------------------------------------------------------------------------------
1438
1439
1441 std::string_view name,
1442 std::shared_ptr<RCollectionNTupleWriter> collectionNTuple,
1443 std::unique_ptr<RNTupleModel> collectionModel)
1444 : RFieldBase(name, "", ENTupleStructure::kCollection, true /* isSimple */)
1445 , fCollectionNTuple(collectionNTuple)
1446{
1447 for (unsigned i = 0; i < collectionModel->GetFieldZero()->fSubFields.size(); ++i) {
1448 auto& subField = collectionModel->GetFieldZero()->fSubFields[i];
1449 Attach(std::move(subField));
1450 }
1451 SetDescription(collectionModel->GetDescription());
1452}
1453
1454
1456{
1457 RColumnModel modelIndex(EColumnType::kIndex, true /* isSorted*/);
1458 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(
1459 Detail::RColumn::Create<ClusterSize_t, EColumnType::kIndex>(modelIndex, 0)));
1460}
1461
1463{
1464 EnsureColumnType({EColumnType::kIndex}, 0, desc);
1465 GenerateColumnsImpl();
1466}
1467
1468
1469std::unique_ptr<ROOT::Experimental::Detail::RFieldBase>
1471{
1472 auto result = std::make_unique<RCollectionField>(newName, fCollectionNTuple, RNTupleModel::Create());
1473 for (auto& f : fSubFields) {
1474 auto clone = f->Clone(f->GetName());
1475 result->Attach(std::move(clone));
1476 }
1477 return result;
1478}
1479
1480
1482 *fCollectionNTuple->GetOffsetPtr() = 0;
1483}
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
#define f(i)
Definition RSha256.hxx:104
#define c(i)
Definition RSha256.hxx:101
@ kIsDefinedInStd
Definition TDictionary.h:98
#define R__ASSERT(e)
Definition TError.h:118
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
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:130
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:386
virtual void GenerateColumnsImpl()=0
Creates the backing columns corresponsing to the field type for writing.
std::vector< std::unique_ptr< RFieldBase > > fSubFields
Collections and classes own sub fields.
Definition RField.hxx:95
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:137
virtual void DestroyValue(const RFieldValue &value, bool dtorOnly=false)
Releases the resources acquired during GenerateValue (memory and constructor) This implementation wor...
Definition RField.cxx:271
friend class ROOT::Experimental::RCollectionField
Definition RField.hxx:73
void ConnectPageSink(RPageSink &pageSink)
Fields and their columns live in the void until connected to a physical page storage.
Definition RField.cxx:342
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:309
void Flush() const
Ensure that all received items are written from page buffers to the storage.
Definition RField.cxx:301
virtual void CommitCluster()
Perform housekeeping tasks for global to cluster-local index translation.
Definition RField.hxx:230
void SetDescription(std::string_view description)
Definition RField.hxx:245
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:278
static RResult< void > EnsureValidFieldName(std::string_view fieldName)
Check whether a given string is a valid field name.
Definition RField.cxx:232
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:149
void ConnectPageSource(RPageSource &pageSource)
Definition RField.cxx:353
virtual std::size_t AppendImpl(const RFieldValue &value)
Operations on values of complex types, e.g.
Definition RField.cxx:251
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:243
virtual void AcceptVisitor(RFieldVisitor &visitor) const
Definition RField.cxx:364
virtual void ReadGlobalImpl(NTupleSize_t globalIndex, RFieldValue *value)
Definition RField.cxx:257
void Attach(std::unique_ptr< Detail::RFieldBase > child)
Add a new subfield to the list of nested fields.
Definition RField.cxx:283
std::vector< RFieldBase * > GetSubFields() const
Definition RField.cxx:291
RFieldValue GenerateValue()
Generates an object of the field type and allocates new initialized memory according to the type.
Definition RField.cxx:264
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 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 RNTupleDescriptor & GetDescriptor() const
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:1289
Detail::RFieldValue CaptureValue(void *where) final
Creates a value from a memory location with an already constructed object.
Definition RField.cxx:1283
void ReadInClusterImpl(const RClusterIndex &clusterIndex, Detail::RFieldValue *value) final
Definition RField.cxx:1245
void ReadGlobalImpl(NTupleSize_t globalIndex, Detail::RFieldValue *value) final
Definition RField.cxx:1236
RArrayField(std::string_view fieldName, std::unique_ptr< Detail::RFieldBase > itemField, std::size_t arrayLength)
Definition RField.cxx:1209
void AcceptVisitor(Detail::RFieldVisitor &visitor) const final
Definition RField.cxx:1300
void GenerateColumnsImpl() final
Creates the backing columns corresponsing to the field type for writing.
Definition RField.cxx:1255
size_t GetValueSize() const final
The number of bytes taken by a value of the appropriate type.
Definition RField.hxx:433
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:1272
size_t GetAlignment() const final
For many types, the alignment requirement is equal to the size; otherwise override.
Definition RField.hxx:434
std::size_t AppendImpl(const Detail::RFieldValue &value) final
Operations on values of complex types, e.g.
Definition RField.cxx:1226
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:1220
The field for a class with dictionary.
Definition RField.hxx:291
Detail::RFieldValue CaptureValue(void *where) final
Creates a value from a memory location with an already constructed object.
Definition RField.cxx:861
static constexpr const char * kPrefixInherited
Prefix used in the subfield names generated for base classes.
Definition RField.hxx:302
size_t GetValueSize() const override
The number of bytes taken by a value of the appropriate type.
Definition RField.cxx:879
void Attach(std::unique_ptr< Detail::RFieldBase > child, RSubFieldInfo info)
Definition RField.cxx:803
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:868
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:811
std::size_t AppendImpl(const Detail::RFieldValue &value) final
Operations on values of complex types, e.g.
Definition RField.cxx:816
void AcceptVisitor(Detail::RFieldVisitor &visitor) const override
Definition RField.cxx:884
void ReadInClusterImpl(const RClusterIndex &clusterIndex, Detail::RFieldValue *value) final
Definition RField.cxx:833
void GenerateColumnsImpl() final
Creates the backing columns corresponsing to the field type for writing.
Definition RField.cxx:841
RClassField(std::string_view fieldName, std::string_view className, TClass *classp)
Definition RField.cxx:773
void ReadGlobalImpl(NTupleSize_t globalIndex, Detail::RFieldValue *value) final
Definition RField.cxx:825
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:854
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
void CommitCluster() final
Perform housekeeping tasks for global to cluster-local index translation.
Definition RField.cxx:1481
void GenerateColumnsImpl() final
Creates the backing columns corresponsing to the field type for writing.
Definition RField.cxx:1455
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:1470
Holds the static meta-data of a column in a tree.
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:431
std::unique_ptr< Detail::RFieldBase > CloneImpl(std::string_view newName) const
Called by Clone(), which additionally copies the on-disk ID.
Definition RField.cxx:413
std::unique_ptr< REntry > GenerateEntry() const
Generates managed values for the top-level sub fields.
Definition RField.cxx:422
Classes with dictionaries that can be inspected by TClass.
Definition RField.hxx:480
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()
std::size_t AppendImpl(const Detail::RFieldValue &value) final
Operations on values of complex types, e.g.
Definition RField.cxx:922
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:914
std::size_t GetItemPadding(std::size_t baseOffset, std::size_t itemAlignment) const
Definition RField.cxx:903
void ReadGlobalImpl(NTupleSize_t globalIndex, Detail::RFieldValue *value) final
Definition RField.cxx:933
Detail::RFieldValue CaptureValue(void *where) final
Creates a value from a memory location with an already constructed object.
Definition RField.cxx:976
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:983
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:963
void ReadInClusterImpl(const RClusterIndex &clusterIndex, Detail::RFieldValue *value) final
Definition RField.cxx:943
void AcceptVisitor(Detail::RFieldVisitor &visitor) const final
Definition RField.cxx:995
RRecordField(std::string_view fieldName, std::vector< std::unique_ptr< Detail::RFieldBase > > &itemFields)
Definition RField.cxx:891
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
Detail::RFieldValue CaptureValue(void *where) override
Creates a value from a memory location with an already constructed object.
Definition RField.cxx:1090
void CommitCluster() final
Perform housekeeping tasks for global to cluster-local index translation.
Definition RField.cxx:1108
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:1013
void AcceptVisitor(Detail::RFieldVisitor &visitor) const final
Definition RField.cxx:1113
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:1096
void ReadGlobalImpl(NTupleSize_t globalIndex, Detail::RFieldValue *value) final
Definition RField.cxx:1034
void GenerateColumnsImpl() final
Creates the backing columns corresponsing to the field type for writing.
Definition RField.cxx:1058
RVectorField(std::string_view fieldName, std::unique_ptr< Detail::RFieldBase > itemField)
Definition RField.cxx:1003
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:1076
std::size_t AppendImpl(const Detail::RFieldValue &value) final
Operations on values of complex types, e.g.
Definition RField.cxx:1019
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:3756
TList * GetListOfBases()
Return list containing the TBaseClass(es) of a class.
Definition TClass.cxx:3622
Long_t Property() const
Returns the properties of the TClass as a bit field stored as a Long_t value.
Definition TClass.cxx:6072
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:2966
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.
constexpr DescriptorId_t kInvalidDescriptorId
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
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 ...
Wrap the 32bit integer in a struct in order to avoid template specialization clash with std::uint32_t...