Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RFile.hxx
Go to the documentation of this file.
1/// \file ROOT/RFile.hxx
2/// \ingroup Base ROOT7
3/// \author Giacomo Parolini <giacomo.parolini@cern.ch>
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 <memory>
14#include <string_view>
15#include <typeinfo>
16
17class TFile;
18class TKey;
19
20namespace ROOT {
21namespace Experimental {
22
23class RFile;
24struct RFileKeyInfo;
25
26namespace Internal {
27
29
30} // namespace Internal
31
32/**
33\class ROOT::Experimental::RFile
34\ingroup RFile
35\brief An interface to read from, or write to, a ROOT file, as well as performing other common operations.
36
37## When and why should you use RFile
38
39RFile is a modern and minimalistic interface to ROOT files, both local and remote, that can be used instead of TFile
40when the following conditions are met:
41- you want a simple interface that makes it easy to do things right and hard to do things wrong;
42- you only need basic Put/Get operations and don't need the more advanced TFile/TDirectory functionalities;
43- you want more robustness and better error reporting for those operations;
44- you want clearer ownership semantics expressed through the type system rather than having objects "automagically"
45 handled for you via implicit ownership of raw pointers.
46
47RFile doesn't try to cover the entirety of use cases covered by TFile/TDirectory/TDirectoryFile and is not
48a 1:1 replacement for them. It is meant to simplify the most common use cases and make them easier to handle by
49minimizing the amount of ROOT-specific quirks and conforming to more standard C++ practices.
50
51## Ownership model
52
53RFile handles ownership via smart pointers, typically std::unique_ptr.
54
55When getting an object from the file (via RFile::Get) you get back a unique copy of the object. Calling `Get` on the
56same object twice produces two independent clones of the object. The ownership over that object is solely on the caller
57and not shared with the RFile. Therefore, the object will remain valid after closing or destroying the RFile that
58generated it. This also means that any modification done to the object are **not** reflected to the file automatically:
59to update the object in the file you need to write it again (via RFile::Overwrite).
60
61RFile::Put and RFile::Overwrite are the way to write objects to the file. Both methods take a const reference to the
62object to write and don't change the ownership of the object in any way. Calling Put or Overwrite doesn't guarantee that
63the object is immediately written to the underlying storage: to ensure that, you need to call RFile::Flush (or close the
64file).
65
66## Directories
67
68Differently from TFile, the RFile class itself is not also a "directory". In fact, there is no RDirectory class at all.
69
70Directories are still an existing concept in RFile (since they are a concept in the ROOT binary format),
71but they are usually interacted with indirectly, via the use of filesystem-like string-based paths. If you Put an object
72in an RFile under the path "path/to/object", "object" will be stored under directory "to" which is in turn stored under
73directory "path". This hierarchy is encoded in the ROOT file itself and it can provide some optimization and/or
74conveniencies when querying objects.
75
76For the most part, it is convenient to think about RFile in terms of a key-value storage where string-based paths are
77used to refer to arbitrary objects. However, given the hierarchical nature of ROOT files, certain filesystem-like
78properties are applied to paths, for ease of use: the '/' character is treated specially as the directory separator;
79multiple '/' in a row are collapsed into one (since RFile doesn't allow directories with empty names).
80
81At the moment, RFile doesn't allow getting directories via Get, nor writing ones via Put (this may change in the
82future).
83
84## Sample usage
85Opening an RFile (for writing) and writing an object to it:
86~~~{.cpp}
87auto rfile = ROOT::RFile::Recreate("my_file.root");
88auto myObj = TH1D("h", "h", 10, 0, 1);
89rfile->Put(myObj.GetName(), myObj);
90~~~
91
92Opening an RFile (for reading) and reading an object from it:
93~~~{.cpp}
94auto rfile = ROOT::RFile::Open("my_file.root");
95auto myObj = file->Get<TH1D>("h");
96~~~
97*/
98class RFile final {
103
104 std::unique_ptr<TFile> fFile;
105
106 // Outlined to avoid including TFile.h
107 explicit RFile(std::unique_ptr<TFile> file);
108
109 /// Gets object `path` from the file and returns an **owning** pointer to it.
110 /// The caller should immediately wrap it into a unique_ptr of the type described by `type`.
111 [[nodiscard]] void *GetUntyped(std::string_view path, const std::type_info &type) const;
112
113 /// Writes `obj` to file, without taking its ownership.
114 void PutUntyped(std::string_view path, const std::type_info &type, const void *obj, std::uint32_t flags);
115
116 /// \see Put
117 template <typename T>
118 void PutInternal(std::string_view path, const T &obj, std::uint32_t flags)
119 {
120 PutUntyped(path, typeid(T), &obj, flags);
121 }
122
123 /// Given `path`, returns the TKey corresponding to the object at that path (assuming the path is fully split, i.e.
124 /// "a/b/c" always means "object 'c' inside directory 'b' inside directory 'a'").
125 /// IMPORTANT: `path` must have been validated/normalized via ValidateAndNormalizePath() (see RFile.cxx).
126 TKey *GetTKey(std::string_view path) const;
127
128public:
129 // This is arbitrary, but it's useful to avoid pathological cases
130 static constexpr int kMaxPathNesting = 1000;
131
132 ///// Factory methods /////
133
134 /// Opens the file for reading. `path` may be a regular file path or a remote URL.
135 /// \throw ROOT::RException if the file at `path` could not be opened.
136 static std::unique_ptr<RFile> Open(std::string_view path);
137
138 /// Opens the file for reading/writing, overwriting it if it already exists.
139 /// \throw ROOT::RException if a file could not be created at `path` (e.g. if the specified
140 /// directory tree does not exist).
141 static std::unique_ptr<RFile> Recreate(std::string_view path);
142
143 /// Opens the file for updating, creating a new one if it doesn't exist.
144 /// \throw ROOT::RException if the file at `path` could neither be read nor created
145 /// (e.g. if the specified directory tree does not exist).
146 static std::unique_ptr<RFile> Update(std::string_view path);
147
148 ///// Instance methods /////
149
150 // Outlined to avoid including TFile.h
152
153 /// Retrieves an object from the file.
154 /// `path` should be a string such that `IsValidPath(path) == true`, otherwise an exception will be thrown.
155 /// See \ref ValidateAndNormalizePath() for info about valid path names.
156 /// If the object is not there returns a null pointer.
157 template <typename T>
158 std::unique_ptr<T> Get(std::string_view path) const
159 {
160 void *obj = GetUntyped(path, typeid(T));
161 return std::unique_ptr<T>(static_cast<T *>(obj));
162 }
163
164 /// Puts an object into the file.
165 /// The application retains ownership of the object.
166 /// `path` should be a string such that `IsValidPath(path) == true`, otherwise an exception will be thrown.
167 /// See \ref ValidateAndNormalizePath() for info about valid path names.
168 ///
169 /// Throws a RException if `path` already identifies a valid object or directory.
170 /// Throws a RException if the file was opened in read-only mode.
171 template <typename T>
172 void Put(std::string_view path, const T &obj)
173 {
174 PutInternal(path, obj, /* flags = */ 0);
175 }
176
177 /// Puts an object into the file, overwriting any previously-existing object at that path.
178 /// The application retains ownership of the object.
179 ///
180 /// If an object already exists at that path, it is kept as a backup cycle unless `backupPrevious` is false.
181 /// Note that even if `backupPrevious` is false, any existing cycle except the latest will be preserved.
182 ///
183 /// Throws a RException if `path` is already the path of a directory.
184 /// Throws a RException if the file was opened in read-only mode.
185 template <typename T>
186 void Overwrite(std::string_view path, const T &obj, bool backupPrevious = true)
187 {
188 std::uint32_t flags = kPutAllowOverwrite;
190 PutInternal(path, obj, flags);
191 }
192
193 /// Writes all objects and the file structure to disk.
194 /// Returns the number of bytes written.
195 size_t Flush();
196
197 /// Flushes the RFile if needed and closes it, disallowing any further reading or writing.
198 void Close();
199};
200
201} // namespace Experimental
202} // namespace ROOT
203
204#endif
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t type
An interface to read from, or write to, a ROOT file, as well as performing other common operations.
Definition RFile.hxx:98
void Close()
Flushes the RFile if needed and closes it, disallowing any further reading or writing.
Definition RFile.cxx:377
static constexpr int kMaxPathNesting
Definition RFile.hxx:130
static std::unique_ptr< RFile > Recreate(std::string_view path)
Opens the file for reading/writing, overwriting it if it already exists.
Definition RFile.cxx:213
std::unique_ptr< TFile > fFile
Definition RFile.hxx:104
size_t Flush()
Writes all objects and the file structure to disk.
Definition RFile.cxx:372
static std::unique_ptr< RFile > Update(std::string_view path)
Opens the file for updating, creating a new one if it doesn't exist.
Definition RFile.cxx:200
void PutInternal(std::string_view path, const T &obj, std::uint32_t flags)
Definition RFile.hxx:118
TKey * GetTKey(std::string_view path) const
Given path, returns the TKey corresponding to the object at that path (assuming the path is fully spl...
Definition RFile.cxx:226
static std::unique_ptr< RFile > Open(std::string_view path)
Opens the file for reading.
Definition RFile.cxx:187
std::unique_ptr< T > Get(std::string_view path) const
Retrieves an object from the file.
Definition RFile.hxx:158
void Overwrite(std::string_view path, const T &obj, bool backupPrevious=true)
Puts an object into the file, overwriting any previously-existing object at that path.
Definition RFile.hxx:186
void PutUntyped(std::string_view path, const std::type_info &type, const void *obj, std::uint32_t flags)
Writes obj to file, without taking its ownership.
Definition RFile.cxx:301
void Put(std::string_view path, const T &obj)
Puts an object into the file.
Definition RFile.hxx:172
RFile(std::unique_ptr< TFile > file)
Definition RFile.cxx:183
void * GetUntyped(std::string_view path, const std::type_info &type) const
Gets object path from the file and returns an owning pointer to it.
Definition RFile.cxx:271
A log configuration for a channel, e.g.
Definition RLogger.hxx:98
A ROOT file is an on-disk file, usually with extension .root, that stores objects in a file-system-li...
Definition TFile.h:131
Book space in a file, create I/O buffers, to fill them, (un)compress them.
Definition TKey.h:28
ROOT::RLogChannel & RFileLog()
Definition RFile.cxx:22