Skip to content

Commit e6a96b0

Browse files
silverweeddpiparo
authored andcommitted
[rfile] Implement GetKeyInfo()
1 parent e87b145 commit e6a96b0

File tree

3 files changed

+67
-2
lines changed

3 files changed

+67
-2
lines changed

io/io/inc/ROOT/RFile.hxx

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,9 @@
1111
#include <ROOT/RError.hxx>
1212

1313
#include <deque>
14-
#include <memory>
14+
#include <functional>
1515
#include <iostream>
16+
#include <memory>
1617
#include <string_view>
1718
#include <typeinfo>
1819

@@ -24,12 +25,15 @@ namespace ROOT {
2425
namespace Experimental {
2526

2627
class RFile;
27-
struct RFileKeyInfo;
2828

2929
namespace Internal {
3030

3131
ROOT::RLogChannel &RFileLog();
3232

33+
/// Returns an **owning** pointer to the object referenced by `key`. The caller must delete this pointer.
34+
/// This method is meant to only be used by the pythonization.
35+
[[nodiscard]] void *RFile_GetObjectFromKey(RFile &file, const RKeyInfo &key);
36+
3337
} // namespace Internal
3438

3539
namespace Detail {
@@ -59,6 +63,7 @@ Querying this information can be done via RFile::ListKeys(). Reading an object's
5963
doesn't deserialize the full object, so it's a relatively lightweight operation.
6064
*/
6165
class RKeyInfo final {
66+
friend class ROOT::Experimental::RFile;
6267
friend class ROOT::Experimental::RFileKeyIterable;
6368

6469
public:
@@ -216,6 +221,8 @@ auto myObj = file->Get<TH1D>("h");
216221
~~~
217222
*/
218223
class RFile final {
224+
friend void *Internal::RFile_GetObjectFromKey(RFile &file, const RKeyInfo &key);
225+
219226
/// Flags used in PutInternal()
220227
enum PutFlags {
221228
/// When encountering an object at the specified path, overwrite it with the new one instead of erroring out.
@@ -357,6 +364,9 @@ public:
357364
return RFileKeyIterable(fFile.get(), basePath, flags);
358365
}
359366

367+
/// Retrieves information about the key of object at `path`, if one exists.
368+
std::optional<RKeyInfo> GetKeyInfo(std::string_view path) const;
369+
360370
/// Prints the internal structure of this RFile to the given stream.
361371
void Print(std::ostream &out = std::cout) const;
362372
};

io/io/src/RFile.cxx

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,17 @@ static void EnsureFileOpenAndBinary(const TFile *tfile, std::string_view path)
178178
throw ROOT::RException(R__FAIL("Opened file " + std::string(path) + " is not a ROOT binary file"));
179179
}
180180

181+
static std::string ReconstructFullKeyPath(const TKey &key)
182+
{
183+
std::string path = key.GetName();
184+
TDirectory *parent = key.GetMotherDir();
185+
while (parent && parent->GetMotherDir()) {
186+
path = std::string(parent->GetName()) + "/" + path;
187+
parent = parent->GetMotherDir();
188+
}
189+
return path;
190+
}
191+
181192
/////////////////////////////////////////////////////////////////////////////////////////////////
182193
std::pair<std::string_view, std::string_view> ROOT::Experimental::Detail::DecomposePath(std::string_view path)
183194
{
@@ -513,3 +524,24 @@ void RFile::Close()
513524
// NOTE: this also flushes the file internally
514525
fFile.reset();
515526
}
527+
528+
std::optional<ROOT::Experimental::RKeyInfo> RFile::GetKeyInfo(std::string_view path) const
529+
{
530+
const TKey *key = GetTKey(path);
531+
if (!key)
532+
return {};
533+
534+
RKeyInfo keyInfo;
535+
keyInfo.fPath = ReconstructFullKeyPath(*key);
536+
keyInfo.fClassName = key->GetClassName();
537+
keyInfo.fCycle = key->GetCycle();
538+
keyInfo.fTitle = key->GetTitle();
539+
540+
return keyInfo;
541+
}
542+
543+
void *ROOT::Experimental::Internal::RFile_GetObjectFromKey(RFile &file, const RKeyInfo &key)
544+
{
545+
void *obj = file.GetUntyped(key.GetPath(), key.GetClassName().c_str());
546+
return obj;
547+
}

io/io/test/rfile.cxx

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -701,3 +701,26 @@ TEST(RFile, NormalizedPaths)
701701
EXPECT_NE(file->Get<TH1D>("//a////b/c"), nullptr);
702702
EXPECT_THROW(file->Get<TH1D>("a/b/c/"), ROOT::RException);
703703
}
704+
705+
TEST(RFile, GetKeyInfo)
706+
{
707+
FileRaii fileGuard("test_rfile_getkeyinfo.root");
708+
709+
auto file = RFile::Recreate(fileGuard.GetPath());
710+
std::string obj = "obj";
711+
file->Put("/s", obj);
712+
file->Put("a/b/c", obj);
713+
file->Put("b", obj);
714+
file->Put("/a/d", obj);
715+
716+
EXPECT_EQ(file->GetKeyInfo("foo"), std::nullopt);
717+
718+
for (const std::string_view path : { "/s", "a/b/c", "b", "/a/d" }) {
719+
auto key = file->GetKeyInfo(path);
720+
ASSERT_NE(key, std::nullopt);
721+
EXPECT_EQ(key->GetPath(), path[0] == '/' ? path.substr(1) : path);
722+
EXPECT_EQ(key->GetClassName(), "string");
723+
EXPECT_EQ(key->GetTitle(), "");
724+
EXPECT_EQ(key->GetCycle(), 1);
725+
}
726+
}

0 commit comments

Comments
 (0)