Skip to content

Commit 978733c

Browse files
committed
[rfile] Introduce RFile first prototype
1 parent 3048154 commit 978733c

File tree

5 files changed

+903
-0
lines changed

5 files changed

+903
-0
lines changed

io/io/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ ROOT_LINKER_LIBRARY(RIO
5555
src/TStreamerInfoReadBuffer.cxx
5656
src/TStreamerInfoWriteBuffer.cxx
5757
src/TZIPFile.cxx
58+
src/RFile.cxx
5859
$<TARGET_OBJECTS:RootPcmObjs>
5960
LIBRARIES
6061
${CMAKE_DL_LIBS}
@@ -73,6 +74,7 @@ if(uring)
7374
endif()
7475

7576
ROOT_GENERATE_DICTIONARY(G__RIO
77+
ROOT/RFile.hxx
7678
ROOT/RRawFile.hxx
7779
ROOT/RRawFileTFile.hxx
7880
${rawfile_local_headers}

io/io/inc/ROOT/RFile.hxx

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
/// \file ROOT/RFile.hxx
2+
/// \ingroup Base ROOT7
3+
/// \author Giacomo Parolini <[email protected]>
4+
/// \date 2025-03-19
5+
/// \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback
6+
/// is welcome!
7+
8+
#ifndef ROOT7_RFile
9+
#define ROOT7_RFile
10+
11+
#include <ROOT/RError.hxx>
12+
13+
#include <TClass.h>
14+
15+
#include <string_view>
16+
#include <memory>
17+
18+
class TKey;
19+
class TFile;
20+
21+
namespace ROOT {
22+
namespace Experimental {
23+
24+
class RFile;
25+
struct RFileKeyInfo;
26+
27+
namespace Internal {
28+
29+
ROOT::RLogChannel &RFileLog();
30+
31+
} // namespace Internal
32+
33+
/**
34+
\class ROOT::Experimental::RFile
35+
\ingroup RFile
36+
\brief An interface to read from, or write to, a ROOT file, as well as performing other common operations.
37+
38+
TODO: more in-depth explanation
39+
*/
40+
class RFile final {
41+
enum PutFlags {
42+
kPutAllowOverwrite = 0x1,
43+
kPutOverwriteKeepCycle = 0x2,
44+
};
45+
46+
std::unique_ptr<TFile> fFile;
47+
48+
// Outlined to avoid including TFile.h
49+
explicit RFile(std::unique_ptr<TFile> file);
50+
51+
/// Gets object `path` from the file and returns an **owning** pointer to it.
52+
/// The caller should immediately wrap it into a unique_ptr of the type described by `type`.
53+
[[nodiscard]] void *GetUntyped(std::string_view path, const TClass &type) const;
54+
55+
/// Writes `obj` to file, without taking its ownership.
56+
void PutUntyped(std::string_view path, const TClass &type, const void *obj, std::uint32_t flags);
57+
58+
/// \see Put
59+
template <typename T>
60+
void PutInternal(std::string_view path, const T &obj, std::uint32_t flags)
61+
{
62+
const TClass *cls = TClass::GetClass(typeid(T));
63+
if (!cls) {
64+
throw ROOT::RException(R__FAIL(std::string("Could not determine type of object ") + std::string(path)));
65+
}
66+
PutUntyped(path, *cls, &obj, flags);
67+
}
68+
69+
/// Given `path`, returns the TKey corresponding to the object at that path (assuming the path is fully split, i.e.
70+
/// "a/b/c" always means "object 'c' inside directory 'b' inside directory 'a'").
71+
/// IMPORTANT: `path` must have been validated/normalized via ValidateAndNormalizePath() (see RFile.cxx).
72+
TKey *GetTKey(std::string_view path) const;
73+
74+
public:
75+
// This is arbitrary, but it's useful to avoid pathological cases
76+
static constexpr int kMaxPathNesting = 1000;
77+
78+
///// Factory methods /////
79+
80+
/// Opens the file for reading
81+
static std::unique_ptr<RFile> Open(std::string_view path);
82+
83+
/// Opens the file for reading/writing, overwriting it if it already exists
84+
static std::unique_ptr<RFile> Recreate(std::string_view path);
85+
86+
/// Opens the file for updating
87+
static std::unique_ptr<RFile> OpenForUpdate(std::string_view path);
88+
89+
///// Instance methods /////
90+
91+
// Outlined to avoid including TFile.h
92+
~RFile();
93+
94+
/// Retrieves an object from the file.
95+
/// `path` should be a string such that `IsValidPath(path) == true`, otherwise an exception will be thrown.
96+
/// If the object is not there returns a null pointer.
97+
template <typename T>
98+
std::unique_ptr<T> Get(std::string_view path) const
99+
{
100+
const TClass *cls = TClass::GetClass(typeid(T));
101+
if (!cls) {
102+
throw ROOT::RException(R__FAIL(std::string("Could not determine type of object ") + std::string(path)));
103+
}
104+
void *obj = GetUntyped(path, *cls);
105+
return std::unique_ptr<T>(static_cast<T *>(obj));
106+
}
107+
108+
/// Puts an object into the file.
109+
/// The application retains ownership of the object.
110+
/// `path` should be a string such that `IsValidPath(path) == true`, otherwise an exception will be thrown.
111+
///
112+
/// Throws a RException if `path` already identifies a valid object or directory.
113+
/// Throws a RException if the file was opened in read-only mode.
114+
template <typename T>
115+
void Put(std::string_view path, const T &obj)
116+
{
117+
PutInternal(path, obj, /* flags = */ 0);
118+
}
119+
120+
/// Puts an object into the file, overwriting any previously-existing object at that path.
121+
/// The application retains ownership of the object.
122+
///
123+
/// If an object already exists at that path, it is kept as a backup cycle unless `backupPrevious` is false.
124+
/// Note that even if `backupPrevious` is false, any existing cycle except the latest will be preserved.
125+
///
126+
/// Throws a RException if `path` is already the path of a directory.
127+
/// Throws a RException if the file was opened in read-only mode.
128+
template <typename T>
129+
void Overwrite(std::string_view path, const T &obj, bool backupPrevious = true)
130+
{
131+
std::uint32_t flags = kPutAllowOverwrite;
132+
flags |= backupPrevious * kPutOverwriteKeepCycle;
133+
PutInternal(path, obj, flags);
134+
}
135+
136+
/// Writes all objects to disk with the file structure.
137+
/// Returns the number of bytes written.
138+
size_t Write();
139+
140+
/// Flushes the RFile if needed and closes it, disallowing any further reading or writing.
141+
void Close();
142+
};
143+
144+
} // namespace Experimental
145+
} // namespace ROOT
146+
147+
#endif

0 commit comments

Comments
 (0)