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