Skip to content

Commit 83ebc41

Browse files
committed
[ntuple] add support for leaf count arrays in classes
Maps leaf count arrays in classes to RVecs using Internal::RLeafCountArrayField
1 parent b6e9c1e commit 83ebc41

File tree

2 files changed

+72
-10
lines changed

2 files changed

+72
-10
lines changed

tree/ntuple/src/RFieldMeta.cxx

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -239,13 +239,20 @@ ROOT::RClassField::RClassField(std::string_view fieldName, TClass *classp)
239239
}
240240
}
241241

242-
if (IsLeafCountArray(*dataMember)) {
243-
throw RException(R__FAIL(std::string("leaf count arrays are currently unsupported: ") + GetTypeName() + "." +
244-
dataMember->GetName()));
242+
const auto memberName = dataMember->GetName();
243+
std::unique_ptr<RFieldBase> subField;
244+
245+
if (auto realMember = IsLeafCountArray(*dataMember)) {
246+
assert(typeName.length() > 0);
247+
assert(*typeName.rbegin() == '*');
248+
auto itemField = RFieldBase::Create("_0", typeName.substr(0, typeName.length() - 1)).Unwrap();
249+
const std::ptrdiff_t offsetDelta = realMember->GetThisOffset() - dataMember->GetOffset();
250+
subField = std::unique_ptr<RLeafCountArrayField>(new RLeafCountArrayField(
251+
memberName, std::move(itemField), offsetDelta, true /* fHasPersistentCountLeaf */));
252+
} else {
253+
subField = RFieldBase::Create(memberName, typeName).Unwrap();
245254
}
246255

247-
auto subField = RFieldBase::Create(dataMember->GetName(), typeName).Unwrap();
248-
249256
const auto normTypeName = ROOT::Internal::GetNormalizedUnresolvedTypeName(origTypeName);
250257
if (normTypeName == subField->GetTypeName()) {
251258
SetTypeAliasOf(*subField, "");

tree/ntuple/test/rfield_class.cxx

Lines changed: 60 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -492,10 +492,65 @@ TEST(RNTuple, LeafCountInClass)
492492
EXPECT_THAT(err.what(), testing::HasSubstr("count leaf member defined after array"));
493493
}
494494

495-
try {
496-
model->MakeField<LeafCountInClass>("f");
497-
FAIL() << "class with leaf count array should throw";
498-
} catch (const ROOT::RException &err) {
499-
EXPECT_THAT(err.what(), testing::HasSubstr("leaf count arrays are currently unsupported"));
495+
FileRaii fileGuard("test_ntuple_leaf_count_in_class.root");
496+
497+
{
498+
auto f = model->MakeField<LeafCountInClass>("f");
499+
auto writer = ROOT::RNTupleWriter::Recreate(std::move(model), "ntpl", fileGuard.GetPath());
500+
f->fPayload1 = new unsigned char[2];
501+
f->fPayload2 = new unsigned char[2];
502+
503+
f->fSize = 1;
504+
f->fPayload1[0] = 2;
505+
f->fPayload2[0] = 3;
506+
writer->Fill();
507+
f->fSize = 0;
508+
writer->Fill();
509+
f->fSize = 2;
510+
f->fPayload1[0] = 4;
511+
f->fPayload1[1] = 5;
512+
f->fPayload2[0] = 6;
513+
f->fPayload2[1] = 7;
514+
writer->Fill();
515+
516+
delete[] f->fPayload1;
517+
delete[] f->fPayload2;
500518
}
519+
520+
auto reader = ROOT::RNTupleReader::Open("ntpl", fileGuard.GetPath());
521+
EXPECT_EQ(3u, reader->GetNEntries());
522+
523+
auto viewPayload1 = reader->GetView<ROOT::RVec<unsigned char>>("f.fPayload1");
524+
auto viewPayload2 = reader->GetView<ROOT::RVec<unsigned char>>("f.fPayload2");
525+
EXPECT_EQ(1u, viewPayload1(0).size());
526+
EXPECT_EQ(2u, viewPayload1(0).at(0));
527+
EXPECT_EQ(1u, viewPayload2(0).size());
528+
EXPECT_EQ(3u, viewPayload2(0).at(0));
529+
530+
EXPECT_EQ(0u, viewPayload1(1).size());
531+
EXPECT_EQ(0u, viewPayload2(1).size());
532+
533+
EXPECT_EQ(2u, viewPayload1(2).size());
534+
EXPECT_EQ(4u, viewPayload1(2).at(0));
535+
EXPECT_EQ(5u, viewPayload1(2).at(1));
536+
EXPECT_EQ(2u, viewPayload2(2).size());
537+
EXPECT_EQ(6u, viewPayload2(2).at(0));
538+
EXPECT_EQ(7u, viewPayload2(2).at(1));
539+
540+
auto f = reader->GetModel().GetDefaultEntry().GetPtr<LeafCountInClass>("f");
541+
542+
reader->LoadEntry(0);
543+
EXPECT_EQ(1, f->fSize);
544+
EXPECT_EQ(2, f->fPayload1[0]);
545+
EXPECT_EQ(3, f->fPayload2[0]);
546+
547+
reader->LoadEntry(1);
548+
EXPECT_EQ(0, f->fSize);
549+
550+
reader->LoadEntry(2);
551+
EXPECT_EQ(2, f->fSize);
552+
EXPECT_EQ(4, f->fPayload1[0]);
553+
EXPECT_EQ(5, f->fPayload1[1]);
554+
EXPECT_EQ(6, f->fPayload2[0]);
555+
EXPECT_EQ(7, f->fPayload2[1]);
501556
}

0 commit comments

Comments
 (0)