Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 14 additions & 9 deletions tree/ntuple/inc/ROOT/RField/RFieldSequenceContainer.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class RSoAField;

namespace Internal {
std::unique_ptr<RFieldBase> CreateEmulatedVectorField(std::string_view fieldName, std::unique_ptr<RFieldBase> itemField,
std::string_view emulatedFromType);
std::string_view emulatedFromType, bool isSoA);
}

////////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -212,9 +212,9 @@ public:
/// The field can be constructed as untyped collection through CreateUntyped().
class RVectorField : public RFieldBase {
friend class RArrayAsVectorField; // to get access to the RVectorDeleter
friend std::unique_ptr<RFieldBase> Internal::CreateEmulatedVectorField(std::string_view fieldName,
std::unique_ptr<RFieldBase> itemField,
std::string_view emulatedFromType);
friend std::unique_ptr<RFieldBase>
Internal::CreateEmulatedVectorField(std::string_view fieldName, std::unique_ptr<RFieldBase> itemField,
std::string_view emulatedFromType, bool isSoA);

class RVectorDeleter : public RDeleter {
private:
Expand All @@ -237,11 +237,16 @@ class RVectorField : public RFieldBase {
RDeleter *itemDeleter);

protected:
/// Creates a possibly-untyped VectorField.
/// If `emulatedFromType` is not nullopt, the field is untyped. If the string is empty, it is a "regular"
/// untyped vector field; otherwise, it was created as an emulated field from the given type name.
RVectorField(std::string_view fieldName, std::unique_ptr<RFieldBase> itemField,
std::optional<std::string_view> emulatedFromType);
enum class ECollectionType {
kRegular,
kUntyped,
kEmulatedProxy,
kEmulatedSoA
};
/// Creates a possibly untyped or emulated VectorField.
/// The emulatedFromType information is only needed for the non-regular vectors.
RVectorField(std::string_view fieldName, std::unique_ptr<RFieldBase> itemField, ECollectionType collectionType,
std::string_view enforcedTypeName);

std::unique_ptr<RFieldBase> CloneImpl(std::string_view newName) const final;

Expand Down
10 changes: 6 additions & 4 deletions tree/ntuple/src/RField.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -595,12 +595,14 @@ ROOT::Internal::CreateEmulatedRecordField(std::string_view fieldName,
return std::unique_ptr<RFieldBase>(new RRecordField(fieldName, std::move(itemFields), emulatedFromType));
}

std::unique_ptr<ROOT::RFieldBase> ROOT::Internal::CreateEmulatedVectorField(std::string_view fieldName,
std::unique_ptr<RFieldBase> itemField,
std::string_view emulatedFromType)
std::unique_ptr<ROOT::RFieldBase>
ROOT::Internal::CreateEmulatedVectorField(std::string_view fieldName, std::unique_ptr<RFieldBase> itemField,
std::string_view emulatedFromType, bool isSoA)
{
R__ASSERT(!emulatedFromType.empty());
return std::unique_ptr<RFieldBase>(new RVectorField(fieldName, std::move(itemField), emulatedFromType));
const RVectorField::ECollectionType type =
isSoA ? RVectorField::ECollectionType::kEmulatedSoA : RVectorField::ECollectionType::kEmulatedProxy;
return std::unique_ptr<RFieldBase>(new RVectorField(fieldName, std::move(itemField), type, emulatedFromType));
}

ROOT::RRecordField::RRecordField(std::string_view fieldName, std::vector<std::unique_ptr<RFieldBase>> itemFields,
Expand Down
4 changes: 2 additions & 2 deletions tree/ntuple/src/RFieldBase.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -553,8 +553,8 @@ ROOT::RFieldBase::Create(const std::string &fieldName, const std::string &typeNa
const auto &itemFieldDesc = desc->GetFieldDescriptor(itemFieldId);
auto itemField =
Create(itemFieldDesc.GetFieldName(), itemFieldDesc.GetTypeName(), options, desc, itemFieldId).Unwrap();
auto vecField =
ROOT::Internal::CreateEmulatedVectorField(fieldName, std::move(itemField), fieldDesc.GetTypeName());
auto vecField = ROOT::Internal::CreateEmulatedVectorField(
fieldName, std::move(itemField), fieldDesc.GetTypeName(), fieldDesc.IsSoACollection());
vecField->fTypeAlias = fieldDesc.GetTypeAlias();
return vecField;
} else if (ROOT::Internal::IsCustomEnumFieldDesc(*desc, fieldDesc)) {
Expand Down
32 changes: 24 additions & 8 deletions tree/ntuple/src/RFieldSequenceContainer.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -507,19 +507,26 @@ void ROOT::RRVecField::AcceptVisitor(ROOT::Detail::RFieldVisitor &visitor) const
//------------------------------------------------------------------------------

ROOT::RVectorField::RVectorField(std::string_view fieldName, std::unique_ptr<RFieldBase> itemField,
std::optional<std::string_view> emulatedFromType)
: ROOT::RFieldBase(fieldName, emulatedFromType ? *emulatedFromType : "std::vector<" + itemField->GetTypeName() + ">",
ECollectionType collectionType, std::string_view enforcedTypeName)
: ROOT::RFieldBase(fieldName,
(collectionType != ECollectionType::kRegular) ? enforcedTypeName
: "std::vector<" + itemField->GetTypeName() + ">",
ROOT::ENTupleStructure::kCollection, false /* isSimple */),
fItemSize(itemField->GetValueSize()),
fNWritten(0)
{
// enforcedTypeName must be empty if and only if the collection type is regular or untyped
assert(enforcedTypeName.empty() != (collectionType >= ECollectionType::kEmulatedProxy));

if (itemField->GetAlignment() > kMaxItemAlignment) {
throw RException(
R__FAIL(std::string("Unsupported vector item alignment: ") + std::to_string(itemField->GetAlignment())));
}

if (emulatedFromType && !emulatedFromType->empty())
if (collectionType >= ECollectionType::kEmulatedProxy)
fTraits |= kTraitEmulatedField;
if (collectionType == ECollectionType::kEmulatedSoA)
fTraits |= kTraitSoACollection;

if (!itemField->GetTypeAlias().empty())
fTypeAlias = "std::vector<" + itemField->GetTypeAlias() + ">";
Expand All @@ -530,22 +537,31 @@ ROOT::RVectorField::RVectorField(std::string_view fieldName, std::unique_ptr<RFi
}

ROOT::RVectorField::RVectorField(std::string_view fieldName, std::unique_ptr<RFieldBase> itemField)
: RVectorField(fieldName, std::move(itemField), {})
: RVectorField(fieldName, std::move(itemField), ECollectionType::kRegular, "")
{
}

std::unique_ptr<ROOT::RVectorField>
ROOT::RVectorField::CreateUntyped(std::string_view fieldName, std::unique_ptr<RFieldBase> itemField)
{
return std::unique_ptr<ROOT::RVectorField>(new RVectorField(fieldName, itemField->Clone("_0"), ""));
return std::unique_ptr<ROOT::RVectorField>(
new RVectorField(fieldName, itemField->Clone("_0"), ECollectionType::kUntyped, ""));
}

std::unique_ptr<ROOT::RFieldBase> ROOT::RVectorField::CloneImpl(std::string_view newName) const
{
auto newItemField = fSubfields[0]->Clone(fSubfields[0]->GetFieldName());
auto isUntyped = GetTypeName().empty() || ((fTraits & kTraitEmulatedField) != 0);
auto emulatedFromType = isUntyped ? std::make_optional(GetTypeName()) : std::nullopt;
return std::unique_ptr<ROOT::RVectorField>(new RVectorField(newName, std::move(newItemField), emulatedFromType));
ECollectionType type = ECollectionType::kRegular;
if (GetTypeName().empty()) {
type = ECollectionType::kUntyped;
} else if (fTraits & kTraitEmulatedField) {
type = (fTraits & kTraitSoACollection) ? ECollectionType::kEmulatedSoA : ECollectionType::kEmulatedProxy;
}
std::string_view enforcedTypeName;
if (type != ECollectionType::kRegular)
enforcedTypeName = GetTypeName();
return std::unique_ptr<ROOT::RVectorField>(
new RVectorField(newName, std::move(newItemField), type, enforcedTypeName));
}

std::size_t ROOT::RVectorField::AppendImpl(const void *from)
Expand Down
1 change: 1 addition & 0 deletions tree/ntuple/test/ntuple_emulated.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -984,6 +984,7 @@ TEST(RNTupleEmulated, EmulatedFields_SoA)
const auto &soa = model->GetConstField("f");
EXPECT_EQ(soa.GetTypeName(), "EmulatedSoA");
EXPECT_TRUE(soa.GetTraits() & ROOT::RFieldBase::kTraitEmulatedField);
EXPECT_TRUE(soa.GetTraits() & ROOT::RFieldBase::kTraitSoACollection);
EXPECT_EQ(soa.GetStructure(), ROOT::ENTupleStructure::kCollection);

const auto children = soa.GetConstSubfields();
Expand Down
Loading