Skip to content

Commit 57e7292

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 1d26d19 commit 57e7292

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
@@ -205,13 +205,20 @@ ROOT::RClassField::RClassField(std::string_view fieldName, TClass *classp)
205205
}
206206
}
207207

208-
if (IsLeafCountArray(*dataMember)) {
209-
throw RException(R__FAIL(std::string("leaf count arrays are currently unsupported: ") + GetTypeName() + "." +
210-
dataMember->GetName()));
208+
const auto memberName = dataMember->GetName();
209+
std::unique_ptr<RFieldBase> subField;
210+
211+
if (auto realMember = IsLeafCountArray(*dataMember)) {
212+
assert(typeName.length() > 0);
213+
assert(*typeName.rbegin() == '*');
214+
auto itemField = RFieldBase::Create("_0", typeName.substr(0, typeName.length() - 1)).Unwrap();
215+
const std::ptrdiff_t offsetDelta = realMember->GetThisOffset() - dataMember->GetOffset();
216+
subField = std::unique_ptr<RLeafCountArrayField>(new RLeafCountArrayField(
217+
memberName, std::move(itemField), offsetDelta, true /* fHasPersistentCountLeaf */));
218+
} else {
219+
subField = RFieldBase::Create(memberName, typeName).Unwrap();
211220
}
212221

213-
auto subField = RFieldBase::Create(dataMember->GetName(), typeName).Unwrap();
214-
215222
const auto normTypeName = ROOT::Internal::GetNormalizedUnresolvedTypeName(origTypeName);
216223
if (normTypeName == subField->GetTypeName()) {
217224
SetTypeAliasOf(*subField, "");

tree/ntuple/test/rfield_class.cxx

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

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

0 commit comments

Comments
 (0)