Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ntuple] Ensure type name given by RField<T> is renormalized #17986

Merged
Merged
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
3 changes: 2 additions & 1 deletion tree/ntuple/v7/inc/ROOT/RField.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

#include <ROOT/RError.hxx>
#include <ROOT/RFieldBase.hxx>
#include <ROOT/RFieldUtils.hxx>
#include <ROOT/RNTupleSerialize.hxx>
#include <ROOT/RNTupleUtil.hxx>
#include <ROOT/RSpan.hxx>
Expand Down Expand Up @@ -291,7 +292,7 @@ public:
template <typename T, typename = void>
class RField final : public RClassField {
public:
static std::string TypeName() { return ROOT::Internal::GetDemangledTypeName(typeid(T)); }
static std::string TypeName() { return ROOT::Internal::GetRenormalizedDemangledTypeName(typeid(T)); }
RField(std::string_view name) : RClassField(name, TypeName())
{
static_assert(std::is_class_v<T>, "no I/O support for this basic C++ type");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ struct IsCollectionProxy : HasCollectionProxyMemberType<T> {
template <typename T>
class RField<T, typename std::enable_if<IsCollectionProxy<T>::value>::type> final : public RProxiedCollectionField {
public:
static std::string TypeName() { return ROOT::Internal::GetDemangledTypeName(typeid(T)); }
static std::string TypeName() { return ROOT::Internal::GetRenormalizedDemangledTypeName(typeid(T)); }
RField(std::string_view name) : RProxiedCollectionField(name, TypeName())
{
static_assert(std::is_class<T>::value, "collection proxy unsupported for fundamental types");
Expand Down
5 changes: 5 additions & 0 deletions tree/ntuple/v7/inc/ROOT/RFieldUtils.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

#include <string>
#include <string_view>
#include <typeinfo>
#include <tuple>
#include <vector>

Expand All @@ -26,6 +27,10 @@ std::string GetCanonicalTypePrefix(const std::string &typeName);
/// Given a type name normalized by ROOT meta, renormalize it for RNTuple. E.g., insert std::prefix.
std::string GetRenormalizedTypeName(const std::string &metaNormalizedName);

/// Given a type info ask ROOT meta to demangle it, then renormalize the resulting type name for RNTuple. Useful to
/// ensure that e.g. fundamental types are normalized to the type used by RNTuple (e.g. int -> std::int32_t).
std::string GetRenormalizedDemangledTypeName(const std::type_info &ti);

/// Applies all RNTuple type normalization rules except typedef resolution.
std::string GetNormalizedUnresolvedTypeName(const std::string &origName);

Expand Down
5 changes: 5 additions & 0 deletions tree/ntuple/v7/src/RFieldUtils.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -463,3 +463,8 @@ std::vector<std::string> ROOT::Internal::TokenizeTypeList(std::string_view templ
result.push_back(std::string(typeBegin, typeCursor - typeBegin));
return result;
}

std::string ROOT::Internal::GetRenormalizedDemangledTypeName(const std::type_info &ti)
{
return ROOT::Internal::GetRenormalizedTypeName(ROOT::Internal::GetDemangledTypeName(ti));
}
1 change: 1 addition & 0 deletions tree/ntuple/v7/test/CustomStructLinkDef.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#pragma link C++ class DataVector < int, double> + ;
#pragma link C++ class DataVector < int, float> + ;
#pragma link C++ class DataVector < bool, std::vector < unsigned int>> + ;
#pragma link C++ class DataVector < StructUsingCollectionProxy < int>, double> + ;
#pragma link C++ class DataVector < int, double> ::Inner + ;
#pragma link C++ class DataVector < int, double> ::Inner + ;
#pragma link C++ class DataVector < int, float> ::Inner + ;
Expand Down
6 changes: 6 additions & 0 deletions tree/ntuple/v7/test/ntuple_type_name.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ TEST(RNTuple, TClassDefaultTemplateParameter)
model->AddField(RFieldBase::Create("f4", "struct DataVector<bool,vector<unsigned>>").Unwrap());
model->AddField(RFieldBase::Create("f5", "DataVector<Double32_t>").Unwrap());
model->AddField(RFieldBase::Create("f6", "DataVector<int, double>").Unwrap());
model->MakeField<DataVector<StructUsingCollectionProxy<int>>>("f7");
auto writer = RNTupleWriter::Recreate(std::move(model), "ntpl", fileGuard.GetPath());
}

Expand Down Expand Up @@ -99,6 +100,11 @@ TEST(RNTuple, TClassDefaultTemplateParameter)
auto v1 = reader->GetView<DataVector<int>>("f1");
auto v3 = reader->GetView<DataVector<int>>("f3");
EXPECT_THROW(reader->GetView<DataVector<int>>("f2"), ROOT::RException);

// Ensure the typed API does not throw an exception
auto f1 = reader->GetModel().GetDefaultEntry().GetPtr<DataVector<int>>("f1");
auto f4 = reader->GetModel().GetDefaultEntry().GetPtr<DataVector<bool, std::vector<unsigned int>>>("f4");
auto f7 = reader->GetModel().GetDefaultEntry().GetPtr<DataVector<StructUsingCollectionProxy<int>>>("f7");
}

TEST(RNTuple, TemplateArgIntegerNormalization)
Expand Down
Loading