Logo ROOT  
Reference Guide
RField.cxx
Go to the documentation of this file.
1/// \file RField.cxx
2/// \ingroup NTuple ROOT7
3/// \author Jakob Blomer <jblomer@cern.ch>
4/// \date 2018-10-15
5/// \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback
6/// is welcome!
7
8/*************************************************************************
9 * Copyright (C) 1995-2019, Rene Brun and Fons Rademakers. *
10 * All rights reserved. *
11 * *
12 * For the licensing terms see $ROOTSYS/LICENSE. *
13 * For the list of contributors see $ROOTSYS/README/CREDITS. *
14 *************************************************************************/
15
16#include <ROOT/RColumn.hxx>
17#include <ROOT/RColumnModel.hxx>
18#include <ROOT/REntry.hxx>
19#include <ROOT/RError.hxx>
20#include <ROOT/RField.hxx>
21#include <ROOT/RFieldValue.hxx>
23#include <ROOT/RLogger.hxx>
24#include <ROOT/RNTuple.hxx>
25#include <ROOT/RNTupleModel.hxx>
26
27#include <TBaseClass.h>
28#include <TClass.h>
29#include <TClassEdit.h>
30#include <TCollection.h>
31#include <TDataMember.h>
32#include <TError.h>
33#include <TList.h>
34
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>
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
423{
424 visitor.VisitFieldZero(*this);
425}
426
427
428//------------------------------------------------------------------------------
429
430
432{
433 RColumnModel model(EColumnType::kIndex, true /* isSorted*/);
434 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(
435 Detail::RColumn::Create<ClusterSize_t, EColumnType::kIndex>(model, 0)));
436}
437
439{
440 EnsureColumnType({EColumnType::kIndex}, 0, desc);
441 GenerateColumnsImpl();
442}
443
445{
446 visitor.VisitClusterSizeField(*this);
447}
448
449//------------------------------------------------------------------------------
450
452{
453 RColumnModel model(EColumnType::kChar, false /* isSorted*/);
454 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(Detail::RColumn::Create<
455 char, EColumnType::kChar>(model, 0)));
456}
457
459{
460 EnsureColumnType({EColumnType::kChar}, 0, desc);
461 GenerateColumnsImpl();
462}
463
465{
466 visitor.VisitCharField(*this);
467}
468
469//------------------------------------------------------------------------------
470
472{
473 RColumnModel model(EColumnType::kInt8, false /* isSorted*/);
474 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(Detail::RColumn::Create<
475 std::int8_t, EColumnType::kInt8>(model, 0)));
476}
477
478void ROOT::Experimental::RField<std::int8_t>::GenerateColumnsImpl(const RNTupleDescriptor &desc)
479{
480 EnsureColumnType({EColumnType::kInt8}, 0, desc);
481 GenerateColumnsImpl();
482}
483
484void ROOT::Experimental::RField<std::int8_t>::AcceptVisitor(Detail::RFieldVisitor &visitor) const
485{
486 visitor.VisitInt8Field(*this);
487}
488
489//------------------------------------------------------------------------------
490
492{
493 RColumnModel model(EColumnType::kInt8, false /* isSorted*/);
494 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(Detail::RColumn::Create<
495 std::uint8_t, EColumnType::kInt8>(model, 0)));
496}
497
499{
500 EnsureColumnType({EColumnType::kInt8}, 0, desc);
501 GenerateColumnsImpl();
502}
503
504void ROOT::Experimental::RField<std::uint8_t>::AcceptVisitor(Detail::RFieldVisitor &visitor) const
505{
506 visitor.VisitUInt8Field(*this);
507}
508
509//------------------------------------------------------------------------------
510
511
513{
514 RColumnModel model(EColumnType::kBit, false /* isSorted*/);
515 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(
516 Detail::RColumn::Create<bool, EColumnType::kBit>(model, 0)));
517}
518
520{
521 EnsureColumnType({EColumnType::kBit}, 0, desc);
522 GenerateColumnsImpl();
523}
524
526{
527 visitor.VisitBoolField(*this);
528}
529
530//------------------------------------------------------------------------------
531
532
534{
535 RColumnModel model(EColumnType::kReal32, false /* isSorted*/);
536 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(
537 Detail::RColumn::Create<float, EColumnType::kReal32>(model, 0)));
538}
539
541{
542 EnsureColumnType({EColumnType::kReal32}, 0, desc);
543 GenerateColumnsImpl();
544}
545
547{
548 visitor.VisitFloatField(*this);
549}
550
551
552//------------------------------------------------------------------------------
553
555{
556 RColumnModel model(EColumnType::kReal64, false /* isSorted*/);
557 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(
558 Detail::RColumn::Create<double, EColumnType::kReal64>(model, 0)));
559}
560
562{
563 EnsureColumnType({EColumnType::kReal64}, 0, desc);
564 GenerateColumnsImpl();
565}
566
568{
569 visitor.VisitDoubleField(*this);
570}
571
572//------------------------------------------------------------------------------
573
575{
576 RColumnModel model(EColumnType::kInt16, false /* isSorted*/);
577 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(Detail::RColumn::Create<
578 std::int16_t, EColumnType::kInt16>(model, 0)));
579}
580
582{
583 EnsureColumnType({EColumnType::kInt16}, 0, desc);
584 GenerateColumnsImpl();
585}
586
587void ROOT::Experimental::RField<std::int16_t>::AcceptVisitor(Detail::RFieldVisitor &visitor) const
588{
589 visitor.VisitInt16Field(*this);
590}
591
592//------------------------------------------------------------------------------
593
595{
596 RColumnModel model(EColumnType::kInt16, false /* isSorted*/);
597 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(Detail::RColumn::Create<
598 std::uint16_t, EColumnType::kInt16>(model, 0)));
599}
600
602{
603 EnsureColumnType({EColumnType::kInt16}, 0, desc);
604 GenerateColumnsImpl();
605}
606
607void ROOT::Experimental::RField<std::uint16_t>::AcceptVisitor(Detail::RFieldVisitor &visitor) const
608{
609 visitor.VisitUInt16Field(*this);
610}
611
612//------------------------------------------------------------------------------
613
615{
616 RColumnModel model(EColumnType::kInt32, false /* isSorted*/);
617 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(Detail::RColumn::Create<
618 std::int32_t, EColumnType::kInt32>(model, 0)));
619}
620
622{
623 EnsureColumnType({EColumnType::kInt32}, 0, desc);
624 GenerateColumnsImpl();
625}
626
627void ROOT::Experimental::RField<std::int32_t>::AcceptVisitor(Detail::RFieldVisitor &visitor) const
628{
629 visitor.VisitIntField(*this);
630}
631
632//------------------------------------------------------------------------------
633
635{
636 RColumnModel model(EColumnType::kInt32, false /* isSorted*/);
637 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(
638 Detail::RColumn::Create<std::uint32_t, EColumnType::kInt32>(model, 0)));
639}
640
642{
643 EnsureColumnType({EColumnType::kInt32}, 0, desc);
644 GenerateColumnsImpl();
645}
646
647void ROOT::Experimental::RField<std::uint32_t>::AcceptVisitor(Detail::RFieldVisitor &visitor) const
648{
649 visitor.VisitUInt32Field(*this);
650}
651
652//------------------------------------------------------------------------------
653
655{
656 RColumnModel model(EColumnType::kInt64, false /* isSorted*/);
657 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(
658 Detail::RColumn::Create<std::uint64_t, EColumnType::kInt64>(model, 0)));
659}
660
662{
663 EnsureColumnType({EColumnType::kInt64}, 0, desc);
664 GenerateColumnsImpl();
665}
666
667void ROOT::Experimental::RField<std::uint64_t>::AcceptVisitor(Detail::RFieldVisitor &visitor) const
668{
669 visitor.VisitUInt64Field(*this);
670}
671
672//------------------------------------------------------------------------------
673
675{
676 RColumnModel model(EColumnType::kInt64, false /* isSorted*/);
677 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(
678 Detail::RColumn::Create<std::int64_t, EColumnType::kInt64>(model, 0)));
679}
680
682{
683 auto type = EnsureColumnType({EColumnType::kInt64, EColumnType::kInt32}, 0, desc);
684 RColumnModel model(type, false /* isSorted*/);
685 if (type == EColumnType::kInt64) {
686 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(
687 Detail::RColumn::Create<std::int64_t, EColumnType::kInt64>(model, 0)));
688 } else {
689 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(
690 Detail::RColumn::Create<std::int64_t, EColumnType::kInt32>(model, 0)));
691 }
692}
693
694void ROOT::Experimental::RField<std::int64_t>::AcceptVisitor(Detail::RFieldVisitor &visitor) const
695{
696 visitor.VisitInt64Field(*this);
697}
698
699//------------------------------------------------------------------------------
700
702{
703 RColumnModel modelIndex(EColumnType::kIndex, true /* isSorted*/);
704 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(
705 Detail::RColumn::Create<ClusterSize_t, EColumnType::kIndex>(modelIndex, 0)));
706
707 RColumnModel modelChars(EColumnType::kChar, false /* isSorted*/);
708 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(
709 Detail::RColumn::Create<char, EColumnType::kChar>(modelChars, 1)));
710}
711
712void ROOT::Experimental::RField<std::string>::GenerateColumnsImpl(const RNTupleDescriptor &desc)
713{
714 EnsureColumnType({EColumnType::kIndex}, 0, desc);
715 EnsureColumnType({EColumnType::kChar}, 1, desc);
716 GenerateColumnsImpl();
717}
718
720{
721 auto typedValue = value.Get<std::string>();
722 auto length = typedValue->length();
723 Detail::RColumnElement<char> elemChars(const_cast<char*>(typedValue->data()));
724 fColumns[1]->AppendV(elemChars, length);
725 fIndex += length;
726 fColumns[0]->Append(fElemIndex);
727 return length + sizeof(fElemIndex);
728}
729
732{
733 auto typedValue = value->Get<std::string>();
734 RClusterIndex collectionStart;
735 ClusterSize_t nChars;
736 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &nChars);
737 if (nChars == 0) {
738 typedValue->clear();
739 } else {
740 typedValue->resize(nChars);
741 Detail::RColumnElement<char> elemChars(const_cast<char*>(typedValue->data()));
742 fColumns[1]->ReadV(collectionStart, nChars, &elemChars);
743 }
744}
745
747{
748 fIndex = 0;
749}
750
751void ROOT::Experimental::RField<std::string>::AcceptVisitor(Detail::RFieldVisitor &visitor) const
752{
753 visitor.VisitStringField(*this);
754}
755
756//------------------------------------------------------------------------------
757
758
760 : RClassField(fieldName, className, TClass::GetClass(std::string(className).c_str()))
761{
762}
763
765 : ROOT::Experimental::Detail::RFieldBase(fieldName, className, ENTupleStructure::kRecord, false /* isSimple */)
766 , fClass(classp)
767{
768 if (fClass == nullptr) {
769 throw std::runtime_error("RField: no I/O support for type " + std::string(className));
770 }
771 // Avoid accidentally supporting std types through TClass.
773 throw RException(R__FAIL(std::string(className) + " is not supported"));
774 }
775
776 int i = 0;
778 TClass *c = baseClass->GetClassPointer();
779 auto subField = Detail::RFieldBase::Create(std::string(kPrefixInherited) + "_" + std::to_string(i),
780 c->GetName()).Unwrap();
781 Attach(std::move(subField),
782 RSubFieldInfo{kBaseClass, static_cast<std::size_t>(baseClass->GetDelta())});
783 i++;
784 }
786 if (!dataMember->IsPersistent())
787 continue;
788 auto subField = Detail::RFieldBase::Create(dataMember->GetName(), dataMember->GetFullTypeName()).Unwrap();
789 Attach(std::move(subField),
790 RSubFieldInfo{kDataMember, static_cast<std::size_t>(dataMember->GetOffset())});
791 }
792}
793
794void ROOT::Experimental::RClassField::Attach(std::unique_ptr<Detail::RFieldBase> child, RSubFieldInfo info)
795{
796 fMaxAlignment = std::max(fMaxAlignment, child->GetAlignment());
797 fSubFieldsInfo.push_back(info);
798 RFieldBase::Attach(std::move(child));
799}
800
801std::unique_ptr<ROOT::Experimental::Detail::RFieldBase>
803{
804 return std::unique_ptr<RClassField>(new RClassField(newName, GetType(), fClass));
805}
806
808 std::size_t nbytes = 0;
809 for (unsigned i = 0; i < fSubFields.size(); i++) {
810 auto memberValue = fSubFields[i]->CaptureValue(value.Get<unsigned char>() + fSubFieldsInfo[i].fOffset);
811 nbytes += fSubFields[i]->Append(memberValue);
812 }
813 return nbytes;
814}
815
817{
818 for (unsigned i = 0; i < fSubFields.size(); i++) {
819 auto memberValue = fSubFields[i]->CaptureValue(value->Get<unsigned char>() + fSubFieldsInfo[i].fOffset);
820 fSubFields[i]->Read(globalIndex, &memberValue);
821 }
822}
823
825{
826 for (unsigned i = 0; i < fSubFields.size(); i++) {
827 auto memberValue = fSubFields[i]->CaptureValue(value->Get<unsigned char>() + fSubFieldsInfo[i].fOffset);
828 fSubFields[i]->Read(clusterIndex, &memberValue);
829 }
830}
831
833{
834}
835
837{
838}
839
841{
842 return Detail::RFieldValue(true /* captureFlag */, this, fClass->New(where));
843}
844
846{
847 fClass->Destructor(value.GetRawPtr(), true /* dtorOnly */);
848 if (!dtorOnly)
849 free(value.GetRawPtr());
850}
851
853{
854 return Detail::RFieldValue(true /* captureFlat */, this, where);
855}
856
857
858std::vector<ROOT::Experimental::Detail::RFieldValue>
860{
861 std::vector<Detail::RFieldValue> result;
862 for (unsigned i = 0; i < fSubFields.size(); i++) {
863 auto memberValue = fSubFields[i]->CaptureValue(value.Get<unsigned char>() + fSubFieldsInfo[i].fOffset);
864 result.emplace_back(memberValue);
865 }
866 return result;
867}
868
869
871{
872 return fClass->GetClassSize();
873}
874
876{
877 visitor.VisitClassField(*this);
878}
879
880//------------------------------------------------------------------------------
881
883 std::string_view fieldName, std::vector<std::unique_ptr<Detail::RFieldBase>> &itemFields)
884 : ROOT::Experimental::Detail::RFieldBase(fieldName, "", ENTupleStructure::kRecord, false /* isSimple */)
885{
886 for (auto &item : itemFields) {
887 fMaxAlignment = std::max(fMaxAlignment, item->GetAlignment());
888 fSize += GetItemPadding(fSize, item->GetAlignment()) + item->GetValueSize();
889 Attach(std::move(item));
890 }
891}
892
893
894std::size_t ROOT::Experimental::RRecordField::GetItemPadding(std::size_t baseOffset, std::size_t itemAlignment) const
895{
896 if (itemAlignment > 1) {
897 auto remainder = baseOffset % itemAlignment;
898 if (remainder != 0)
899 return itemAlignment - remainder;
900 }
901 return 0;
902}
903
904std::unique_ptr<ROOT::Experimental::Detail::RFieldBase>
906{
907 std::vector<std::unique_ptr<Detail::RFieldBase>> cloneItems;
908 for (auto &item : fSubFields)
909 cloneItems.emplace_back(item->Clone(item->GetName()));
910 return std::make_unique<RRecordField>(newName, cloneItems);
911}
912
914 std::size_t nbytes = 0;
915 std::size_t offset = 0;
916 for (auto &item : fSubFields) {
917 auto memberValue = item->CaptureValue(value.Get<unsigned char>() + offset);
918 nbytes += item->Append(memberValue);
919 offset += GetItemPadding(offset, item->GetAlignment()) + item->GetValueSize();
920 }
921 return nbytes;
922}
923
925{
926 std::size_t offset = 0;
927 for (auto &item : fSubFields) {
928 auto memberValue = item->CaptureValue(value->Get<unsigned char>() + offset);
929 item->Read(globalIndex, &memberValue);
930 offset += GetItemPadding(offset, item->GetAlignment()) + item->GetValueSize();
931 }
932}
933
935{
936 std::size_t offset = 0;
937 for (auto &item : fSubFields) {
938 auto memberValue = item->CaptureValue(value->Get<unsigned char>() + offset);
939 item->Read(clusterIndex, &memberValue);
940 offset += GetItemPadding(offset, item->GetAlignment()) + item->GetValueSize();
941 }
942}
943
945{
946 std::size_t offset = 0;
947 for (auto &item : fSubFields) {
948 item->GenerateValue(static_cast<unsigned char *>(where) + offset);
949 offset += GetItemPadding(offset, item->GetAlignment()) + item->GetValueSize();
950 }
951 return Detail::RFieldValue(true /* captureFlag */, this, where);
952}
953
955{
956 std::size_t offset = 0;
957 for (auto &item : fSubFields) {
958 auto memberValue = item->CaptureValue(value.Get<unsigned char>() + offset);
959 item->DestroyValue(memberValue, true /* dtorOnly */);
960 offset += GetItemPadding(offset, item->GetAlignment()) + item->GetValueSize();
961 }
962
963 if (!dtorOnly)
964 free(value.GetRawPtr());
965}
966
968{
969 return Detail::RFieldValue(true /* captureFlag */, this, where);
970}
971
972
973std::vector<ROOT::Experimental::Detail::RFieldValue>
975{
976 std::size_t offset = 0;
977 std::vector<Detail::RFieldValue> result;
978 for (auto &item : fSubFields) {
979 result.emplace_back(item->CaptureValue(value.Get<unsigned char>() + offset));
980 offset += GetItemPadding(offset, item->GetAlignment()) + item->GetValueSize();
981 }
982 return result;
983}
984
985
987{
988 visitor.VisitRecordField(*this);
989}
990
991//------------------------------------------------------------------------------
992
993
995 std::string_view fieldName, std::unique_ptr<Detail::RFieldBase> itemField)
996 : ROOT::Experimental::Detail::RFieldBase(
997 fieldName, "std::vector<" + itemField->GetType() + ">", ENTupleStructure::kCollection, false /* isSimple */)
998 , fItemSize(itemField->GetValueSize()), fNWritten(0)
999{
1000 Attach(std::move(itemField));
1001}
1002
1003std::unique_ptr<ROOT::Experimental::Detail::RFieldBase>
1005{
1006 auto newItemField = fSubFields[0]->Clone(fSubFields[0]->GetName());
1007 return std::make_unique<RVectorField>(newName, std::move(newItemField));
1008}
1009
1011 auto typedValue = value.Get<std::vector<char>>();
1012 R__ASSERT((typedValue->size() % fItemSize) == 0);
1013 std::size_t nbytes = 0;
1014 auto count = typedValue->size() / fItemSize;
1015 for (unsigned i = 0; i < count; ++i) {
1016 auto itemValue = fSubFields[0]->CaptureValue(typedValue->data() + (i * fItemSize));
1017 nbytes += fSubFields[0]->Append(itemValue);
1018 }
1019 Detail::RColumnElement<ClusterSize_t> elemIndex(&fNWritten);
1020 fNWritten += count;
1021 fColumns[0]->Append(elemIndex);
1022 return nbytes + sizeof(elemIndex);
1023}
1024
1026{
1027 auto typedValue = value->Get<std::vector<char>>();
1028
1029 ClusterSize_t nItems;
1030 RClusterIndex collectionStart;
1031 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &nItems);
1032
1033 auto oldNItems = typedValue->size() / fItemSize;
1034 for (std::size_t i = nItems; i < oldNItems; ++i) {
1035 auto itemValue = fSubFields[0]->CaptureValue(typedValue->data() + (i * fItemSize));
1036 fSubFields[0]->DestroyValue(itemValue, true /* dtorOnly */);
1037 }
1038 typedValue->resize(nItems * fItemSize);
1039 for (std::size_t i = oldNItems; i < nItems; ++i) {
1040 fSubFields[0]->GenerateValue(typedValue->data() + (i * fItemSize));
1041 }
1042
1043 for (std::size_t i = 0; i < nItems; ++i) {
1044 auto itemValue = fSubFields[0]->CaptureValue(typedValue->data() + (i * fItemSize));
1045 fSubFields[0]->Read(collectionStart + i, &itemValue);
1046 }
1047}
1048
1050{
1051 RColumnModel modelIndex(EColumnType::kIndex, true /* isSorted*/);
1052 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(
1053 Detail::RColumn::Create<ClusterSize_t, EColumnType::kIndex>(modelIndex, 0)));
1054}
1055
1057{
1058 EnsureColumnType({EColumnType::kIndex}, 0, desc);
1059 GenerateColumnsImpl();
1060}
1061
1063{
1064 return Detail::RFieldValue(this, reinterpret_cast<std::vector<char>*>(where));
1065}
1066
1068{
1069 auto vec = static_cast<std::vector<char>*>(value.GetRawPtr());
1070 R__ASSERT((vec->size() % fItemSize) == 0);
1071 auto nItems = vec->size() / fItemSize;
1072 for (unsigned i = 0; i < nItems; ++i) {
1073 auto itemValue = fSubFields[0]->CaptureValue(vec->data() + (i * fItemSize));
1074 fSubFields[0]->DestroyValue(itemValue, true /* dtorOnly */);
1075 }
1076 vec->~vector();
1077 if (!dtorOnly)
1078 free(vec);
1079}
1080
1082{
1083 return Detail::RFieldValue(true /* captureFlag */, this, where);
1084}
1085
1086std::vector<ROOT::Experimental::Detail::RFieldValue>
1088{
1089 auto vec = static_cast<std::vector<char>*>(value.GetRawPtr());
1090 R__ASSERT((vec->size() % fItemSize) == 0);
1091 auto nItems = vec->size() / fItemSize;
1092 std::vector<Detail::RFieldValue> result;
1093 for (unsigned i = 0; i < nItems; ++i) {
1094 result.emplace_back(fSubFields[0]->CaptureValue(vec->data() + (i * fItemSize)));
1095 }
1096 return result;
1097}
1098
1100{
1101 fNWritten = 0;
1102}
1103
1105{
1106 visitor.VisitVectorField(*this);
1107}
1108
1109
1110//------------------------------------------------------------------------------
1111
1112
1114 : ROOT::Experimental::Detail::RFieldBase(name, "std::vector<bool>", ENTupleStructure::kCollection,
1115 false /* isSimple */)
1116{
1117 Attach(std::make_unique<RField<bool>>("_0"));
1118}
1119
1120std::size_t ROOT::Experimental::RField<std::vector<bool>>::AppendImpl(const Detail::RFieldValue& value) {
1121 auto typedValue = value.Get<std::vector<bool>>();
1122 auto count = typedValue->size();
1123 for (unsigned i = 0; i < count; ++i) {
1124 bool bval = (*typedValue)[i];
1125 auto itemValue = fSubFields[0]->CaptureValue(&bval);
1126 fSubFields[0]->Append(itemValue);
1127 }
1128 Detail::RColumnElement<ClusterSize_t> elemIndex(&fNWritten);
1129 fNWritten += count;
1130 fColumns[0]->Append(elemIndex);
1131 return count + sizeof(elemIndex);
1132}
1133
1134void ROOT::Experimental::RField<std::vector<bool>>::ReadGlobalImpl(NTupleSize_t globalIndex, Detail::RFieldValue* value)
1135{
1136 auto typedValue = value->Get<std::vector<bool>>();
1137
1138 ClusterSize_t nItems;
1139 RClusterIndex collectionStart;
1140 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &nItems);
1141
1142 typedValue->resize(nItems);
1143 for (unsigned i = 0; i < nItems; ++i) {
1144 bool bval;
1145 auto itemValue = fSubFields[0]->GenerateValue(&bval);
1146 fSubFields[0]->Read(collectionStart + i, &itemValue);
1147 (*typedValue)[i] = bval;
1148 }
1149}
1150
1151void ROOT::Experimental::RField<std::vector<bool>>::GenerateColumnsImpl()
1152{
1153 RColumnModel modelIndex(EColumnType::kIndex, true /* isSorted*/);
1154 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(
1155 Detail::RColumn::Create<ClusterSize_t, EColumnType::kIndex>(modelIndex, 0)));
1156}
1157
1158void ROOT::Experimental::RField<std::vector<bool>>::GenerateColumnsImpl(const RNTupleDescriptor &desc)
1159{
1160 EnsureColumnType({EColumnType::kIndex}, 0, desc);
1161 GenerateColumnsImpl();
1162}
1163
1164std::vector<ROOT::Experimental::Detail::RFieldValue>
1165ROOT::Experimental::RField<std::vector<bool>>::SplitValue(const Detail::RFieldValue& value) const
1166{
1167 const static bool trueValue = true;
1168 const static bool falseValue = false;
1169
1170 auto typedValue = value.Get<std::vector<bool>>();
1171 auto count = typedValue->size();
1172 std::vector<Detail::RFieldValue> result;
1173 for (unsigned i = 0; i < count; ++i) {
1174 if ((*typedValue)[i])
1175 result.emplace_back(fSubFields[0]->CaptureValue(const_cast<bool *>(&trueValue)));
1176 else
1177 result.emplace_back(fSubFields[0]->CaptureValue(const_cast<bool *>(&falseValue)));
1178 }
1179 return result;
1180}
1181
1182
1183void ROOT::Experimental::RField<std::vector<bool>>::DestroyValue(const Detail::RFieldValue& value, bool dtorOnly)
1184{
1185 auto vec = static_cast<std::vector<bool>*>(value.GetRawPtr());
1186 vec->~vector();
1187 if (!dtorOnly)
1188 free(vec);
1189}
1190
1191void ROOT::Experimental::RField<std::vector<bool>>::AcceptVisitor(Detail::RFieldVisitor &visitor) const
1192{
1193 visitor.VisitVectorBoolField(*this);
1194}
1195
1196
1197//------------------------------------------------------------------------------
1198
1199
1201 std::string_view fieldName, std::unique_ptr<Detail::RFieldBase> itemField, std::size_t arrayLength)
1202 : ROOT::Experimental::Detail::RFieldBase(
1203 fieldName, "std::array<" + itemField->GetType() + "," + std::to_string(arrayLength) + ">",
1204 ENTupleStructure::kLeaf, false /* isSimple */, arrayLength)
1205 , fItemSize(itemField->GetValueSize()), fArrayLength(arrayLength)
1206{
1207 Attach(std::move(itemField));
1208}
1209
1210std::unique_ptr<ROOT::Experimental::Detail::RFieldBase>
1212{
1213 auto newItemField = fSubFields[0]->Clone(fSubFields[0]->GetName());
1214 return std::make_unique<RArrayField>(newName, std::move(newItemField), fArrayLength);
1215}
1216
1218 std::size_t nbytes = 0;
1219 auto arrayPtr = value.Get<unsigned char>();
1220 for (unsigned i = 0; i < fArrayLength; ++i) {
1221 auto itemValue = fSubFields[0]->CaptureValue(arrayPtr + (i * fItemSize));
1222 nbytes += fSubFields[0]->Append(itemValue);
1223 }
1224 return nbytes;
1225}
1226
1228{
1229 auto arrayPtr = value->Get<unsigned char>();
1230 for (unsigned i = 0; i < fArrayLength; ++i) {
1231 auto itemValue = fSubFields[0]->GenerateValue(arrayPtr + (i * fItemSize));
1232 fSubFields[0]->Read(globalIndex * fArrayLength + i, &itemValue);
1233 }
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(RClusterIndex(clusterIndex.GetClusterId(), clusterIndex.GetIndex() * fArrayLength + i),
1242 &itemValue);
1243 }
1244}
1245
1247{
1248}
1249
1251{
1252}
1253
1255{
1256 auto arrayPtr = reinterpret_cast<unsigned char *>(where);
1257 for (unsigned i = 0; i < fArrayLength; ++i) {
1258 fSubFields[0]->GenerateValue(arrayPtr + (i * fItemSize));
1259 }
1260 return Detail::RFieldValue(true /* captureFlag */, this, where);
1261}
1262
1264{
1265 auto arrayPtr = value.Get<unsigned char>();
1266 for (unsigned i = 0; i < fArrayLength; ++i) {
1267 auto itemValue = fSubFields[0]->CaptureValue(arrayPtr + (i * fItemSize));
1268 fSubFields[0]->DestroyValue(itemValue, true /* dtorOnly */);
1269 }
1270 if (!dtorOnly)
1271 free(arrayPtr);
1272}
1273
1275{
1276 return Detail::RFieldValue(true /* captureFlag */, this, where);
1277}
1278
1279std::vector<ROOT::Experimental::Detail::RFieldValue>
1281{
1282 auto arrayPtr = value.Get<unsigned char>();
1283 std::vector<Detail::RFieldValue> result;
1284 for (unsigned i = 0; i < fArrayLength; ++i) {
1285 auto itemValue = fSubFields[0]->CaptureValue(arrayPtr + (i * fItemSize));
1286 result.emplace_back(itemValue);
1287 }
1288 return result;
1289}
1290
1292{
1293 visitor.VisitArrayField(*this);
1294}
1295
1296//------------------------------------------------------------------------------
1297
1298#if __cplusplus >= 201703L
1299std::string ROOT::Experimental::RVariantField::GetTypeList(const std::vector<Detail::RFieldBase *> &itemFields)
1300{
1301 std::string result;
1302 for (size_t i = 0; i < itemFields.size(); ++i) {
1303 result += itemFields[i]->GetType() + ",";
1304 }
1305 R__ASSERT(!result.empty()); // there is always at least one variant
1306 result.pop_back(); // remove trailing comma
1307 return result;
1308}
1309
1310ROOT::Experimental::RVariantField::RVariantField(
1311 std::string_view fieldName, const std::vector<Detail::RFieldBase *> &itemFields)
1312 : ROOT::Experimental::Detail::RFieldBase(fieldName,
1313 "std::variant<" + GetTypeList(itemFields) + ">", ENTupleStructure::kVariant, false /* isSimple */)
1314{
1315 auto nFields = itemFields.size();
1316 R__ASSERT(nFields > 0);
1317 fNWritten.resize(nFields, 0);
1318 for (unsigned int i = 0; i < nFields; ++i) {
1319 fMaxItemSize = std::max(fMaxItemSize, itemFields[i]->GetValueSize());
1320 fMaxAlignment = std::max(fMaxAlignment, itemFields[i]->GetAlignment());
1321 Attach(std::unique_ptr<Detail::RFieldBase>(itemFields[i]));
1322 }
1323 fTagOffset = (fMaxItemSize < fMaxAlignment) ? fMaxAlignment : fMaxItemSize;
1324}
1325
1326std::unique_ptr<ROOT::Experimental::Detail::RFieldBase>
1327ROOT::Experimental::RVariantField::CloneImpl(std::string_view newName) const
1328{
1329 auto nFields = fSubFields.size();
1330 std::vector<Detail::RFieldBase *> itemFields;
1331 for (unsigned i = 0; i < nFields; ++i) {
1332 // TODO(jblomer): use unique_ptr in RVariantField constructor
1333 itemFields.emplace_back(fSubFields[i]->Clone(fSubFields[i]->GetName()).release());
1334 }
1335 return std::make_unique<RVariantField>(newName, itemFields);
1336}
1337
1338std::uint32_t ROOT::Experimental::RVariantField::GetTag(void *variantPtr) const
1339{
1340 auto index = *(reinterpret_cast<char *>(variantPtr) + fTagOffset);
1341 return (index < 0) ? 0 : index + 1;
1342}
1343
1344void ROOT::Experimental::RVariantField::SetTag(void *variantPtr, std::uint32_t tag) const
1345{
1346 auto index = reinterpret_cast<char *>(variantPtr) + fTagOffset;
1347 *index = static_cast<char>(tag - 1);
1348}
1349
1350std::size_t ROOT::Experimental::RVariantField::AppendImpl(const Detail::RFieldValue& value)
1351{
1352 auto tag = GetTag(value.GetRawPtr());
1353 std::size_t nbytes = 0;
1354 auto index = 0;
1355 if (tag > 0) {
1356 auto itemValue = fSubFields[tag - 1]->CaptureValue(value.GetRawPtr());
1357 nbytes += fSubFields[tag - 1]->Append(itemValue);
1358 index = fNWritten[tag - 1]++;
1359 }
1360 RColumnSwitch varSwitch(ClusterSize_t(index), tag);
1361 Detail::RColumnElement<RColumnSwitch> elemSwitch(&varSwitch);
1362 fColumns[0]->Append(elemSwitch);
1363 return nbytes + sizeof(RColumnSwitch);
1364}
1365
1366void ROOT::Experimental::RVariantField::ReadGlobalImpl(NTupleSize_t globalIndex, Detail::RFieldValue *value)
1367{
1368 RClusterIndex variantIndex;
1369 std::uint32_t tag;
1370 fPrincipalColumn->GetSwitchInfo(globalIndex, &variantIndex, &tag);
1371 R__ASSERT(tag > 0); // TODO(jblomer): deal with invalid variants
1372
1373 auto itemValue = fSubFields[tag - 1]->GenerateValue(value->GetRawPtr());
1374 fSubFields[tag - 1]->Read(variantIndex, &itemValue);
1375 SetTag(value->GetRawPtr(), tag);
1376}
1377
1378void ROOT::Experimental::RVariantField::GenerateColumnsImpl()
1379{
1380 RColumnModel modelSwitch(EColumnType::kSwitch, false);
1381 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(
1382 Detail::RColumn::Create<RColumnSwitch, EColumnType::kSwitch>(modelSwitch, 0)));
1383}
1384
1385void ROOT::Experimental::RVariantField::GenerateColumnsImpl(const RNTupleDescriptor &desc)
1386{
1387 EnsureColumnType({EColumnType::kSwitch}, 0, desc);
1388 GenerateColumnsImpl();
1389}
1390
1391ROOT::Experimental::Detail::RFieldValue ROOT::Experimental::RVariantField::GenerateValue(void *where)
1392{
1393 memset(where, 0, GetValueSize());
1394 fSubFields[0]->GenerateValue(where);
1395 SetTag(where, 1);
1396 return Detail::RFieldValue(this, reinterpret_cast<unsigned char *>(where));
1397}
1398
1399void ROOT::Experimental::RVariantField::DestroyValue(const Detail::RFieldValue& value, bool dtorOnly)
1400{
1401 auto variantPtr = value.GetRawPtr();
1402 auto tag = GetTag(variantPtr);
1403 if (tag > 0) {
1404 auto itemValue = fSubFields[tag - 1]->CaptureValue(variantPtr);
1405 fSubFields[tag - 1]->DestroyValue(itemValue, true /* dtorOnly */);
1406 }
1407 if (!dtorOnly)
1408 free(variantPtr);
1409}
1410
1411ROOT::Experimental::Detail::RFieldValue ROOT::Experimental::RVariantField::CaptureValue(void *where)
1412{
1413 return Detail::RFieldValue(true /* captureFlag */, this, where);
1414}
1415
1416size_t ROOT::Experimental::RVariantField::GetValueSize() const
1417{
1418 return fMaxItemSize + fMaxAlignment; // TODO: fix for more than 255 items
1419}
1420
1421void ROOT::Experimental::RVariantField::CommitCluster()
1422{
1423 std::fill(fNWritten.begin(), fNWritten.end(), 0);
1424}
1425#endif
1426
1427
1428//------------------------------------------------------------------------------
1429
1430
1433 std::shared_ptr<RCollectionNTupleWriter> collectionNTuple,
1434 std::unique_ptr<RNTupleModel> collectionModel)
1435 : RFieldBase(name, "", ENTupleStructure::kCollection, true /* isSimple */)
1436 , fCollectionNTuple(collectionNTuple)
1437{
1438 for (unsigned i = 0; i < collectionModel->GetFieldZero()->fSubFields.size(); ++i) {
1439 auto& subField = collectionModel->GetFieldZero()->fSubFields[i];
1440 Attach(std::move(subField));
1441 }
1442 SetDescription(collectionModel->GetDescription());
1443}
1444
1445
1447{
1448 RColumnModel modelIndex(EColumnType::kIndex, true /* isSorted*/);
1449 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(
1450 Detail::RColumn::Create<ClusterSize_t, EColumnType::kIndex>(modelIndex, 0)));
1451}
1452
1454{
1455 EnsureColumnType({EColumnType::kIndex}, 0, desc);
1456 GenerateColumnsImpl();
1457}
1458
1459
1460std::unique_ptr<ROOT::Experimental::Detail::RFieldBase>
1462{
1463 auto result = std::make_unique<RCollectionField>(newName, fCollectionNTuple, RNTupleModel::Create());
1464 for (auto& f : fSubFields) {
1465 auto clone = f->Clone(f->GetName());
1466 result->Attach(std::move(clone));
1467 }
1468 return result;
1469}
1470
1471
1473 *fCollectionNTuple->GetOffsetPtr() = 0;
1474}
uint8_t
Definition: Converters.cxx:876
Cppyy::TCppType_t fClass
#define R__FAIL(msg)
Short-hand to return an RResult<T> in an error state; the RError is implicitly converted into RResult...
Definition: RError.hxx:291
ROOT::Experimental::RField< T > RField
#define f(i)
Definition: RSha256.hxx:104
#define c(i)
Definition: RSha256.hxx:101
@ 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
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
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:1280
Detail::RFieldValue CaptureValue(void *where) final
Creates a value from a memory location with an already constructed object.
Definition: RField.cxx:1274
void ReadInClusterImpl(const RClusterIndex &clusterIndex, Detail::RFieldValue *value) final
Definition: RField.cxx:1236
void ReadGlobalImpl(NTupleSize_t globalIndex, Detail::RFieldValue *value) final
Definition: RField.cxx:1227
RArrayField(std::string_view fieldName, std::unique_ptr< Detail::RFieldBase > itemField, std::size_t arrayLength)
Definition: RField.cxx:1200
void AcceptVisitor(Detail::RFieldVisitor &visitor) const final
Definition: RField.cxx:1291
void GenerateColumnsImpl() final
Creates the backing columns corresponsing to the field type for writing.
Definition: RField.cxx:1246
size_t GetValueSize() const final
The number of bytes taken by a value of the appropriate type.
Definition: RField.hxx:431
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:1263
size_t GetAlignment() const final
For many types, the alignment requirement is equal to the size; otherwise override.
Definition: RField.hxx:432
std::size_t AppendImpl(const Detail::RFieldValue &value) final
Operations on values of complex types, e.g.
Definition: RField.cxx:1217
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:1211
The field for a class with dictionary.
Definition: RField.hxx:289
Detail::RFieldValue CaptureValue(void *where) final
Creates a value from a memory location with an already constructed object.
Definition: RField.cxx:852
static constexpr const char * kPrefixInherited
Prefix used in the subfield names generated for base classes.
Definition: RField.hxx:300
size_t GetValueSize() const override
The number of bytes taken by a value of the appropriate type.
Definition: RField.cxx:870
void Attach(std::unique_ptr< Detail::RFieldBase > child, RSubFieldInfo info)
Definition: RField.cxx:794
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:859
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:802
std::size_t AppendImpl(const Detail::RFieldValue &value) final
Operations on values of complex types, e.g.
Definition: RField.cxx:807
void AcceptVisitor(Detail::RFieldVisitor &visitor) const override
Definition: RField.cxx:875
void ReadInClusterImpl(const RClusterIndex &clusterIndex, Detail::RFieldValue *value) final
Definition: RField.cxx:824
void GenerateColumnsImpl() final
Creates the backing columns corresponsing to the field type for writing.
Definition: RField.cxx:832
RClassField(std::string_view fieldName, std::string_view className, TClass *classp)
Definition: RField.cxx:764
void ReadGlobalImpl(NTupleSize_t globalIndex, Detail::RFieldValue *value) final
Definition: RField.cxx:816
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:845
Addresses a column element or field item relative to a particular cluster, instead of a global NTuple...
Definition: RNTupleUtil.hxx:95
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:1472
void GenerateColumnsImpl() final
Creates the backing columns corresponsing to the field type for writing.
Definition: RField.cxx:1446
RCollectionField(std::string_view name, std::shared_ptr< RCollectionNTupleWriter > collectionNTuple, std::unique_ptr< RNTupleModel > collectionModel)
Definition: RField.cxx:1431
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:1461
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.
Definition: RField.hxx:58
void AcceptVisitor(Detail::RFieldVisitor &visitor) const final
Definition: RField.cxx:422
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
Classes with dictionaries that can be inspected by TClass.
Definition: RField.hxx:478
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:913
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:905
std::size_t GetItemPadding(std::size_t baseOffset, std::size_t itemAlignment) const
Definition: RField.cxx:894
void ReadGlobalImpl(NTupleSize_t globalIndex, Detail::RFieldValue *value) final
Definition: RField.cxx:924
Detail::RFieldValue CaptureValue(void *where) final
Creates a value from a memory location with an already constructed object.
Definition: RField.cxx:967
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:974
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:954
void ReadInClusterImpl(const RClusterIndex &clusterIndex, Detail::RFieldValue *value) final
Definition: RField.cxx:934
void AcceptVisitor(Detail::RFieldVisitor &visitor) const final
Definition: RField.cxx:986
RRecordField(std::string_view fieldName, std::vector< std::unique_ptr< Detail::RFieldBase > > &itemFields)
Definition: RField.cxx:882
RResult<void> has no data member and no Inspect() method but instead a Success() factory method.
Definition: RError.hxx:257
The class is used as a return type for operations that can fail; wraps a value of type T or an RError...
Definition: RError.hxx:195
Detail::RFieldValue CaptureValue(void *where) override
Creates a value from a memory location with an already constructed object.
Definition: RField.cxx:1081
void CommitCluster() final
Perform housekeeping tasks for global to cluster-local index translation.
Definition: RField.cxx:1099
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:1004
void AcceptVisitor(Detail::RFieldVisitor &visitor) const final
Definition: RField.cxx:1104
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:1087
void ReadGlobalImpl(NTupleSize_t globalIndex, Detail::RFieldValue *value) final
Definition: RField.cxx:1025
void GenerateColumnsImpl() final
Creates the backing columns corresponsing to the field type for writing.
Definition: RField.cxx:1049
RVectorField(std::string_view fieldName, std::unique_ptr< Detail::RFieldBase > itemField)
Definition: RField.cxx:994
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:1067
std::size_t AppendImpl(const Detail::RFieldValue &value) final
Operations on values of complex types, e.g.
Definition: RField.cxx:1010
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:3763
TList * GetListOfBases()
Return list containing the TBaseClass(es) of a class.
Definition: TClass.cxx:3629
Long_t Property() const
Returns the properties of the TClass as a bit field stored as a Long_t value.
Definition: TClass.cxx:6038
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:2955
basic_string_view< char > string_view
std::uint64_t NTupleSize_t
Integer type long enough to hold the maximum number of entries in a column.
Definition: RNTupleUtil.hxx:55
RClusterSize ClusterSize_t
Definition: RNTupleUtil.hxx:70
ENTupleStructure
The fields in the ntuple model tree can carry different structural information about the type system.
Definition: RNTupleUtil.hxx:45
constexpr DescriptorId_t kInvalidDescriptorId
Definition: RNTupleUtil.hxx:92
clang::QualType GetNormalizedType(const clang::QualType &type, const cling::Interpreter &interpreter, const TNormalizedCtxt &normCtxt)
Return the type normalized for ROOT, keeping only the ROOT opaque typedef (Double32_t,...
This file contains a specialised ROOT message handler to test for diagnostic in unit tests.
TClass * GetClass(T *)
Definition: TClass.h:658
Type GetType(const std::string &Name)
Definition: Systematics.cxx:34
std::string ResolveTypedef(const char *tname, bool resolveAll=false)
std::string CleanType(const char *typeDesc, int mode=0, const char **tail=0)
Cleanup type description, redundant blanks removed and redundant tail ignored return *tail = pointer ...
fill
Definition: fit1_py.py:6
Wrap the 32bit integer in a struct in order to avoid template specialization clash with std::uint32_t...
Definition: RNTupleUtil.hxx:58
Definition: civetweb.c:2228