Skip to content

[ntuple][RFC] Do type-check in RValue::GetRef with basic data types #18719

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

Draft
wants to merge 11 commits into
base: master
Choose a base branch
from
23 changes: 23 additions & 0 deletions tree/ntuple/inc/ROOT/RFieldBase.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include <string>
#include <string_view>
#include <vector>
#include <cstring>

namespace ROOT {

Expand Down Expand Up @@ -727,9 +728,31 @@ public:
return std::static_pointer_cast<T>(fObjPtr);
}

/**
* Get object reference, already casted to template type
* \note If a the passed template type does not match the field base type name, an exception is thrown
*/
template <typename T>
const T &GetRef() const
{
const auto templName = typeid(T).name();
auto typeName = fField ? fField->GetTypeName() : "";
// if (typeName.substr(0, 25) == "ROOT::RNTupleCardinality<")
// typeName = ROOT::Internal::GetCanonicalTypePrefix(ROOT::Internal::TokenizeTypeList(typeName.substr(25, typeName.length() - 26)).at(0));
if ((std::strncmp(templName, "c", 1) == 0 && typeName != "char" && typeName != "std::int8_t") ||
(std::strncmp(templName, "h", 1) == 0 && typeName != "unsigned char" && typeName != "std::uint8_t" && typeName != "std::byte") ||
(std::strncmp(templName, "s", 1) == 0 && typeName != "short" && typeName != "std::int16_t") ||
(std::strncmp(templName, "t", 1) == 0 && typeName != "unsigned short" && typeName != "std::uint16_t") ||
(std::strncmp(templName, "i", 1) == 0 && typeName != "int" && typeName != "std::int32_t") ||
(std::strncmp(templName, "j", 1) == 0 && typeName != "unsigned int" && typeName != "std::uint32_t" && typeName != "ROOT::RNTupleCardinality<std::uint32_t>") ||
(std::strncmp(templName, "l", 1) == 0 && typeName != "long" && typeName != "std::int64_t") ||
(std::strncmp(templName, "m", 1) == 0 && typeName != "unsigned long" && typeName != "std::uint64_t" && typeName != "ROOT::RNTupleCardinality<std::uint64_t>") ||
(std::strncmp(templName, "f", 1) == 0 && typeName != "float") ||
(std::strncmp(templName, "d", 1) == 0 && typeName != "double") ||
(std::strncmp(templName, "e", 1) == 0 && typeName != "long double")) {
throw RException(
R__FAIL("Mismatch between type name `" + typeName + "` and template type `" + templName + "`."));
}
return *static_cast<T *>(fObjPtr.get());
}

Expand Down
51 changes: 51 additions & 0 deletions tree/ntuple/test/ntuple_view.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,57 @@ TEST(RNTuple, VoidView)
EXPECT_STREQ("pt", viewPt.GetField().GetFieldName().c_str());
}

TEST(RNTuple, VoidViewThrow)
{
FileRaii fileGuard("test_ntuple_voidview_throw.root");

auto model = RNTupleModel::Create();
*model->MakeField<char>("c") = 42;
*model->MakeField<unsigned char>("h") = 42;
*model->MakeField<short>("s") = 42;
*model->MakeField<unsigned short>("t") = 42;
*model->MakeField<int>("i") = 42;
*model->MakeField<unsigned int>("j") = 42;
*model->MakeField<long>("l") = 42;
*model->MakeField<unsigned long>("m") = 42;
*model->MakeField<float>("f") = 42.f;
*model->MakeField<double>("d") = 42.;
{
auto writer = RNTupleWriter::Recreate(std::move(model), "ntpl", fileGuard.GetPath());
writer->Fill();
}

auto reader = RNTupleReader::Open("ntpl", fileGuard.GetPath());
EXPECT_EQ(1u, reader->GetNEntries());
auto vc = reader->GetView<void>("c");
auto vh = reader->GetView<void>("h");
auto vs = reader->GetView<void>("s");
auto vt = reader->GetView<void>("t");
auto vi = reader->GetView<void>("i");
auto vj = reader->GetView<void>("j");
auto vl = reader->GetView<void>("l");
auto vm = reader->GetView<void>("m");
auto vf = reader->GetView<void>("f");
auto vd = reader->GetView<void>("d");
EXPECT_THROW(vc.GetValue().GetRef<short>(), ROOT::RException);
EXPECT_THROW(vh.GetValue().GetRef<unsigned short>(), ROOT::RException);
EXPECT_THROW(vs.GetValue().GetRef<int>(), ROOT::RException);
EXPECT_THROW(vt.GetValue().GetRef<unsigned int>(), ROOT::RException);
EXPECT_THROW(vi.GetValue().GetRef<long>(), ROOT::RException);
EXPECT_THROW(vj.GetValue().GetRef<unsigned long>(), ROOT::RException);
EXPECT_THROW(vl.GetValue().GetRef<short>(), ROOT::RException);
EXPECT_THROW(vm.GetValue().GetRef<unsigned short>(), ROOT::RException);
EXPECT_THROW(vf.GetValue().GetRef<double>(), ROOT::RException);
EXPECT_THROW(vf.GetValue().GetRef<Double_t>(), ROOT::RException);
EXPECT_THROW(vd.GetValue().GetRef<float>(), ROOT::RException);
EXPECT_THROW(vd.GetValue().GetRef<Float_t>(), ROOT::RException);
EXPECT_THROW(vd.GetValue().GetRef<long double>(), ROOT::RException);
vf(0);
EXPECT_FLOAT_EQ(vf.GetValue().GetRef<Float_t>(), 42.f);
vd(0);
EXPECT_FLOAT_EQ(vd.GetValue().GetRef<Double_t>(), 42.);
}

TEST(RNTuple, MissingViewNames)
{
FileRaii fileGuard("test_ntuple_missing_view_names.root");
Expand Down
Loading