Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RFile.cxx
Go to the documentation of this file.
1/// \file v7/src/RFile.cxx
2/// \author Giacomo Parolini <giacomo.parolini@cern.ch>
3/// \date 2025-03-19
4/// \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback
5/// is welcome!
6
7#include "ROOT/RFile.hxx"
8
10#include <ROOT/RLogger.hxx>
11#include <ROOT/RError.hxx>
12
13#include <Byteswap.h>
14#include <TError.h>
15#include <TFile.h>
16#include <TIterator.h>
17#include <TNamed.h>
18#include <TKey.h>
19#include <TList.h>
20#include <TROOT.h>
21
22#include <algorithm>
23#include <cstring>
24
26{
27 static ROOT::RLogChannel sLog("ROOT.File");
28 return sLog;
29}
30
31using ROOT::RFile;
33
34namespace {
35enum class ENameCycleError {
36 kNoError,
37 kAnyCycle,
38 kInvalidSyntax,
39 kCycleTooLarge,
40 kNameEmpty,
41 kCOUNT
42};
43
44struct RNameCycleResult {
45 std::string fName;
46 std::optional<std::int16_t> fCycle;
47 ENameCycleError fError;
48};
49} // namespace
50
51static const char *ToString(ENameCycleError err)
52{
53 static const char *const kErrorStr[] = {"", "", "invalid syntax", "cycle is too large", "name is empty"};
54 static_assert(std::size(kErrorStr) == static_cast<std::size_t>(ENameCycleError::kCOUNT));
55 return kErrorStr[static_cast<std::size_t>(err)];
56}
57
58static ENameCycleError DecodeNumericCycle(const char *str, std::optional<std::int16_t> &out)
59{
60 uint32_t res = 0;
61 do {
62 if (!isdigit(*str))
63 return ENameCycleError::kInvalidSyntax;
64 if (res * 10 > std::numeric_limits<std::int16_t>::max())
65 return ENameCycleError::kCycleTooLarge;
66 res *= 10;
67 res += *str - '0';
68 } while (*++str);
69
70 assert(res < std::numeric_limits<std::int16_t>::max());
71 out = static_cast<std::int16_t>(res);
72
73 return ENameCycleError::kNoError;
74}
75
76static RNameCycleResult DecodeNameCycle(std::string_view nameCycleRaw)
77{
78 RNameCycleResult result{};
79
80 if (nameCycleRaw.empty())
81 return result;
82
83 // Scan the string to find the name length and the semicolon
84 std::size_t semicolonIdx = nameCycleRaw.find_first_of(';');
85
86 if (semicolonIdx == 0) {
87 result.fError = ENameCycleError::kNameEmpty;
88 return result;
89 }
90
91 // Verify that we have at most one ';'
92 if (nameCycleRaw.substr(semicolonIdx + 1).find_first_of(';') != std::string_view::npos) {
93 result.fError = ENameCycleError::kInvalidSyntax;
94 return result;
95 }
96
97 result.fName = nameCycleRaw.substr(0, semicolonIdx);
98 if (semicolonIdx < std::string_view::npos) {
99 if (semicolonIdx == nameCycleRaw.length() - 1 && nameCycleRaw[semicolonIdx] == '*')
100 result.fError = ENameCycleError::kAnyCycle;
101 else
102 result.fError = DecodeNumericCycle(nameCycleRaw.substr(semicolonIdx + 1).data(), result.fCycle);
103 }
104
105 return result;
106}
107
108/// This function first validates, then normalizes the given path in place.
109///
110/// Returns an empty string if `path` is a suitable path to store an object into a RFile,
111/// otherwise returns a description of why that is not the case.
112///
113/// A valid object path must:
114/// - not be empty
115/// - not contain the character '.'
116/// - not contain ASCII control characters or whitespace characters (including tab or newline).
117/// - not contain more than RFile::kMaxPathNesting path fragments (i.e. more than RFile::kMaxPathNesting - 1 '/')
118/// - not end with a '/'
119///
120/// In addition, when *writing* an object to RFile, the character ';' is also banned.
121///
122/// Passing an invalid path to Put will cause it to throw an exception, and
123/// passing an invalid path to Get will always return nullptr.
124///
125/// If required, `path` is modified to make its hierarchy-related meaning consistent. This entails:
126/// - combining any consecutive '/' into a single one;
127/// - stripping any leading '/'.
128///
129static std::string ValidateAndNormalizePath(std::string &path)
130{
131 ////// First, validate path.
132
133 if (path.empty())
134 return "path cannot be empty";
135
136 if (path.back() == '/')
137 return "path cannot end with a '/'";
138
139 bool valid = true;
140 for (char ch : path) {
141 // Disallow control characters, tabs, newlines, whitespace and dot.
142 // NOTE: not short-circuiting or early returning to enable loop vectorization.
143 valid &= !(ch < 33 || ch == '.');
144 }
145 if (!valid)
146 return "path cannot contain control characters, whitespaces or dots";
147
148 //// Path is valid so far, normalize it.
149
150 // Strip all leading '/'
151 {
152 auto nToStrip = 0u;
153 const auto len = path.length();
154 while (nToStrip < len && path[nToStrip] == '/')
155 ++nToStrip;
156
157 if (nToStrip > 0)
158 path.erase(0, nToStrip);
159 }
160
161 // Remove duplicate consecutive '/'
162 const auto it = std::unique(path.begin(), path.end(), [](char a, char b) { return (a == '/' && b == '/'); });
163 path.erase(it, path.end());
164
165 //// After the path has been normalized, check the nesting level by counting how many slashes it contains.
166 const auto nesting = std::count(path.begin(), path.end(), '/');
167 if (nesting > RFile::kMaxPathNesting)
168 return "pathView contains too many levels of nesting";
169
170 return "";
171}
172
173static void EnsureFileOpenAndBinary(const TFile *tfile, std::string_view path)
174{
175 if (!tfile || tfile->IsZombie())
176 throw ROOT::RException(R__FAIL("failed to open file " + std::string(path) + " for reading"));
177
178 if (tfile->IsRaw() || !tfile->IsBinary() || tfile->IsArchive())
179 throw ROOT::RException(R__FAIL("Opened file " + std::string(path) + " is not a ROOT binary file"));
180}
181
182static std::string ReconstructFullKeyPath(const TKey &key)
183{
184 std::string path = key.GetName();
185 TDirectory *parent = key.GetMotherDir();
186 while (parent && parent->GetMotherDir()) {
187 path = std::string(parent->GetName()) + "/" + path;
188 parent = parent->GetMotherDir();
189 }
190 return path;
191}
192
193/////////////////////////////////////////////////////////////////////////////////////////////////
194std::pair<std::string_view, std::string_view> ROOT::Detail::DecomposePath(std::string_view path)
195{
196 auto lastSlashIdx = path.rfind('/');
197 if (lastSlashIdx == std::string_view::npos)
198 return {{}, path};
199
200 auto dirName = path.substr(0, lastSlashIdx + 1);
201 auto pathName = path.substr(lastSlashIdx + 1);
202 return {dirName, pathName};
203}
204
205std::unique_ptr<RFile> RFile::Open(std::string_view path, const ROpenOptions &opts)
206{
207 TDirectory::TContext ctx(nullptr); // XXX: probably not thread safe?
208 const char *mode = opts.fEnableBrowsability ? "READ" : "READ_WITHOUT_GLOBALREGISTRATION";
209 auto tfile = std::unique_ptr<TFile>(TFile::Open(std::string(path).c_str(), mode));
210 EnsureFileOpenAndBinary(tfile.get(), path);
211
212 auto rfile = std::unique_ptr<RFile>(new RFile(std::move(tfile)));
213 return rfile;
214}
215
216std::unique_ptr<RFile> RFile::Update(std::string_view path, const RUpdateOptions &opts)
217{
218 TDirectory::TContext ctx(nullptr); // XXX: probably not thread safe?
219 const char *mode = opts.fEnableBrowsability ? "UPDATE" : "UPDATE_WITHOUT_GLOBALREGISTRATION";
220 auto tfile = std::unique_ptr<TFile>(TFile::Open(std::string(path).c_str(), mode));
221 EnsureFileOpenAndBinary(tfile.get(), path);
222
223 auto rfile = std::unique_ptr<RFile>(new RFile(std::move(tfile)));
224 return rfile;
225}
226
227std::unique_ptr<RFile> RFile::Recreate(std::string_view path, const RRecreateOptions &opts)
228{
229 TDirectory::TContext ctx(nullptr); // XXX: probably not thread safe?
230 const char *mode = opts.fEnableBrowsability ? "RECREATE" : "RECREATE_WITHOUT_GLOBALREGISTRATION";
231 auto tfile = std::unique_ptr<TFile>(TFile::Open(std::string(path).c_str(), mode, "", opts.fCompressionSettings));
232 EnsureFileOpenAndBinary(tfile.get(), path);
233
234 auto rfile = std::unique_ptr<RFile>(new RFile(std::move(tfile)));
235 return rfile;
236}
237
238RFile::RFile(std::unique_ptr<TFile> file) : fFile(std::move(file)) {}
239
240RFile::~RFile() = default;
241
242TKey *RFile::GetTKey(std::string_view path) const
243{
244 // In RFile, differently from TFile, when dealing with a path like "a/b/c", we always consider it to mean
245 // "object 'c' in subdirectory 'b' of directory 'a'". We don't try to get any other of the possible combinations,
246 // including the object called "a/b/c".
247 std::string fullPath = std::string(path);
248 char *dirName = fullPath.data();
249 char *restOfPath = strchr(dirName, '/');
250 TDirectory *dir = fFile.get();
251 while (restOfPath) {
252 // Truncate `dirName` to the position of this '/'.
253 *restOfPath = 0;
254 ++restOfPath;
255 // `restOfPath` should always be a non-empty string unless `path` ends with '/' (which it shouldn't, as we are
256 // supposed to have normalized it before calling this function).
257 assert(*restOfPath);
258
259 dir = dir->GetDirectory(dirName);
260 if (!dir)
261 return nullptr;
262
263 dirName = restOfPath;
264 restOfPath = strchr(restOfPath, '/');
265 }
266 // NOTE: after this loop `dirName` contains the base name of the object.
267
268 // Get the leaf object from the innermost directory.
269 TKey *key = dir->FindKey(dirName);
270 if (key) {
271 // For some reason, FindKey will not return nullptr if we asked for a specific cycle and that cycle
272 // doesn't exist. It will instead return any key whose cycle is *at most* the requested one.
273 // This is very confusing, so in RFile we actually return null if the requested cycle is not there.
274 RNameCycleResult res = DecodeNameCycle(dirName);
275 if (res.fError != ENameCycleError::kAnyCycle) {
276 if (res.fError != ENameCycleError::kNoError) {
277 R__LOG_ERROR(RFileLog()) << "error decoding namecycle '" << dirName << "': " << ToString(res.fError);
278 key = nullptr;
279 } else if (res.fCycle && *res.fCycle != key->GetCycle()) {
280 key = nullptr;
281 }
282 }
283 }
284 return key;
285}
286
287void *RFile::GetUntyped(std::string_view path,
288 std::variant<const char *, std::reference_wrapper<const std::type_info>> type) const
289{
290 if (!fFile)
291 throw ROOT::RException(R__FAIL("File has been closed"));
292
293 std::string pathStr{path};
294
295 struct {
296 TClass *operator()(const char *name) { return TClass::GetClass(name); }
297 TClass *operator()(std::reference_wrapper<const std::type_info> ty) { return TClass::GetClass(ty.get()); }
298 } typeVisitor;
299 const TClass *cls = std::visit(std::move(typeVisitor), type);
300
301 if (!cls)
302 throw ROOT::RException(R__FAIL(std::string("Could not determine type of object ") + pathStr));
303
304 if (auto err = ValidateAndNormalizePath(pathStr); !err.empty())
305 throw RException(R__FAIL("Invalid object pathStr '" + pathStr + "': " + err));
306
307 TKey *key = GetTKey(pathStr);
308 void *obj = key ? key->ReadObjectAny(cls) : nullptr;
309
310 if (obj) {
311 // Disavow any ownership on `obj` unless the object is a TTree, in which case we need to link it to our internal
312 // file for it to be usable.
313 if (auto autoAddFunc = cls->GetDirectoryAutoAdd()) {
314 if (cls->InheritsFrom("TTree")) {
315 autoAddFunc(obj, fFile.get());
316 // NOTE(gparolini): this is a hacky but effective way of preventing the Tree from being deleted by
317 // the internal TFile once we close it. We need to avoid that because this TTree will be returned inside
318 // a unique_ptr and would end up being double-freed if we allowed ROOT to do its own memory management.
320 } else {
321 autoAddFunc(obj, nullptr);
322 }
323 }
324 } else if (key) {
325 R__LOG_INFO(RFileLog()) << "Tried to get object '" << path << "' of type " << cls->GetName()
326 << " but that path contains an object of type " << key->GetClassName();
327 }
328
329 return obj;
330}
331
332void RFile::Put(const TNamed &namedObj, std::string_view dirPath)
333{
334 if (strchr(namedObj.GetName(), '/')) {
335 throw ROOT::RException(R__FAIL(std::string("TNamed object '") + namedObj.GetName() +
336 "' given to RFile::Put cannot have '/' in its name!"));
337 }
338 std::string completePath = (dirPath.empty() ? "" : std::string(dirPath) + '/') + namedObj.GetName();
339 Put(completePath, namedObj, namedObj.GetTitle());
340}
341
342void RFile::PutUntyped(std::string_view pathSV, const std::type_info &type, const void *obj, std::uint32_t flags,
343 std::string_view title)
344{
345 const TClass *cls = TClass::GetClass(type);
346 if (!cls)
347 throw ROOT::RException(R__FAIL(std::string("Could not determine type of object ") + std::string(pathSV)));
348
349 std::string path{pathSV};
350 if (auto err = ValidateAndNormalizePath(path); !err.empty())
351 throw RException(R__FAIL("Invalid object path '" + path + "': " + err));
352
353 if (path.find_first_of(';') != std::string_view::npos) {
354 throw RException(
355 R__FAIL("Invalid object path '" + path +
356 "': character ';' is used to specify an object cycle, which only makes sense when reading."));
357 }
358
359 if (!fFile)
360 throw ROOT::RException(R__FAIL("File has been closed"));
361
362 if (!fFile->IsWritable())
363 throw ROOT::RException(R__FAIL("File is not writable"));
364
365 // If `path` refers to a subdirectory, make sure we always write in an actual TDirectory,
366 // otherwise we may have a mix of top-level objects called "a/b/c" and actual directory
367 // structures.
368 // Sadly, TFile does nothing to prevent this and will happily write "a/b" even if there
369 // is already a directory "a" containing an object "b". We don't want that ambiguity here, so we take extra steps
370 // to ensure it doesn't happen.
371 const auto tokens = ROOT::Split(path, "/");
372 const auto FullPathUntil = [&tokens](auto idx) {
373 return ROOT::Join("/", std::span<const std::string>{tokens.data(), idx + 1});
374 };
375 TDirectory *dir = fFile.get();
376 for (auto tokIdx = 0u; tokIdx < tokens.size() - 1; ++tokIdx) {
377 // Alas, not only does mkdir not fail if the file already contains an object "a/b" and you try
378 // to create dir "a", but even when it does fail it doesn't tell you why.
379 // We obviously don't want to allow the coexistence of regular object named "a/b" and the directory
380 // named "a", so we manually check if each level of nesting doesn't exist already as a non-directory.
381 const TKey *existing = dir->GetKey(tokens[tokIdx].c_str());
382 if (existing && strcmp(existing->GetClassName(), "TDirectory") != 0 &&
383 strcmp(existing->GetClassName(), "TDirectoryFile") != 0) {
384 throw ROOT::RException(R__FAIL("error adding object '" + path + "': failed to create directory '" +
385 FullPathUntil(tokIdx) + "': name already taken by an object of type '" +
386 existing->GetClassName() + "'"));
387 }
388 dir = dir->mkdir(tokens[tokIdx].c_str(), "", true);
389 if (!dir) {
390 throw ROOT::RException(R__FAIL(std::string("failed to create directory ") + FullPathUntil(tokIdx)));
391 }
392 }
393
394 const bool allowOverwrite = (flags & kPutFlag_AllowOverwrite) != 0;
395 const bool backupCycle = (flags & kPutFlag_OverwriteKeepCycle) != 0;
396 const Option_t *writeOpts = "";
397 if (!allowOverwrite) {
398 const TKey *existing = dir->GetKey(tokens[tokens.size() - 1].c_str());
399 if (existing) {
400 throw ROOT::RException(R__FAIL(std::string("trying to overwrite object ") + path + " of type " +
401 existing->GetClassName() + " with another object of type " + cls->GetName()));
402 }
403 } else if (!backupCycle) {
404 writeOpts = "WriteDelete";
405 }
406
407 const char *objName = tokens[tokens.size() - 1].c_str();
408 assert(dynamic_cast<TDirectoryFile *>(dir));
409 int success =
410 static_cast<TDirectoryFile *>(dir)->WriteObjectAny(obj, cls, {objName, std::string(title).c_str()}, writeOpts);
411
412 if (!success) {
413 throw ROOT::RException(R__FAIL(std::string("Failed to write ") + path + " to file"));
414 }
415}
416
418 : fIter(it), fDirPath(path)
419{
420}
421
423
425 : fPattern(pattern), fFlags(flags)
426{
427 if (iter) {
428 fIterStack.emplace_back(iter);
429
430 if (!pattern.empty()) {
431 fRootDirNesting = std::count(pattern.begin(), pattern.end(), '/');
432 // `pattern` may or may not end with '/', but we consider it a directory regardless.
433 // In other words, like in virtually all filesystem operations, "dir" and "dir/" are equivalent.
434 fRootDirNesting += pattern.back() != '/';
435 }
436
437 // Advance the iterator to skip the first key, which is always the TFile key.
438 // This will also skip keys until we reach the first correct key we want to return.
439 Advance();
440 }
441}
442
447
452
454{
455 fCurKey = nullptr;
456
457 const bool recursive = fFlags & RFile::kListRecursive;
458 const bool includeObj = fFlags & RFile::kListObjects;
459 const bool includeDirs = fFlags & RFile::kListDirs;
460
461 // We only want to return keys that refer to user objects, not internal ones, therefore we skip
462 // all keys that have internal class names.
463 while (!fIterStack.empty()) {
464 auto &[iter, dirPath] = fIterStack.back();
465 assert(iter);
466 TObject *keyObj = iter->Next();
467 if (!keyObj) {
468 // reached end of the iteration
469 fIterStack.pop_back();
470 continue;
471 }
472
473 assert(keyObj->IsA() == TClass::GetClass<TKey>());
474 auto key = static_cast<TKey *>(keyObj);
475
476 const std::string dirSep = (dirPath.empty() ? "" : "/");
477 const bool isDir = TClass::GetClass(key->GetClassName())->InheritsFrom(TDirectory::Class());
478
479 if (isDir) {
480 TDirectory *dir = key->ReadObject<TDirectory>();
481 TIterator *innerIter = dir->GetListOfKeys()->MakeIterator();
482 assert(innerIter);
483 fIterStack.emplace_back(innerIter, dirPath + dirSep + dir->GetName());
484 if (!includeDirs)
485 continue;
486 } else if (!includeObj) {
487 continue;
488 }
489
490 // Reconstruct the full path of the key
491 const std::string &fullPath = dirPath + dirSep + key->GetName();
492 assert(!fIterStack.empty());
493 const std::size_t nesting = fIterStack.size() - 1;
494
495 // Skip key if it's the root dir itself
496 if (isDir && fullPath == fPattern)
497 continue;
498
499 // Skip key if it's not a child of root dir
500 if (!ROOT::StartsWith(fullPath, fPattern))
501 continue;
502
503 // Check that we are in the same directory as "rootDir".
504 // Note that for directories we list both the root dir and the immediate children (in non-recursive mode).
505 if (!recursive && nesting != fRootDirNesting &&
506 (!isDir || nesting != static_cast<std::size_t>(fRootDirNesting + 1)))
507 continue;
508
509 // All checks passed: return this key.
510 assert(!fullPath.empty());
511 fCurKey = key;
512 break;
513 }
514}
515
517{
518 if (fIterStack.empty())
519 throw ROOT::RException(R__FAIL("tried to dereference an invalid iterator"));
520
521 const TKey *key = fCurKey;
522 if (!key)
523 throw ROOT::RException(R__FAIL("tried to dereference an invalid iterator"));
524
525 const bool isDir =
526 strcmp(key->GetClassName(), "TDirectory") == 0 || strcmp(key->GetClassName(), "TDirectoryFile") == 0;
527 const auto &dirPath = fIterStack.back().fDirPath;
528
529 RKeyInfo keyInfo;
531 keyInfo.fPath = dirPath;
532 if (!isDir)
533 keyInfo.fPath += std::string(dirPath.empty() ? "" : "/") + key->GetName();
534 keyInfo.fClassName = key->GetClassName();
535 keyInfo.fCycle = key->GetCycle();
536 keyInfo.fTitle = key->GetTitle();
537 return keyInfo;
538}
539
540void RFile::Print(std::ostream &out) const
541{
542 std::vector<RKeyInfo> keys;
543 auto keysIter = ListKeys();
544 for (const auto &key : keysIter) {
545 keys.emplace_back(key);
546 }
547
548 std::sort(keys.begin(), keys.end(), [](const auto &a, const auto &b) { return a.GetPath() < b.GetPath(); });
549 for (const auto &key : keys) {
550 out << key.GetClassName() << " " << key.GetPath() << ";" << key.GetCycle() << ": \"" << key.GetTitle() << "\"\n";
551 }
552}
553
555{
556 return fFile->Write();
557}
558
560{
561 // NOTE: this also flushes the file internally
562 fFile.reset();
563}
564
566 : fPath(ReconstructFullKeyPath(key)),
567 fTitle(key.GetTitle()),
568 fClassName(key.GetClassName()),
569 fCycle(key.GetCycle()),
570 fLenObj(key.GetObjlen()),
571 fNBytesObj(key.GetNbytes() - key.GetKeylen()),
572 fNBytesKey(key.GetKeylen()),
573 fSeekKey(key.GetSeekKey()),
574 fSeekParentDir(key.GetSeekPdir())
575{
576}
577
578std::optional<ROOT::RKeyInfo> RFile::GetKeyInfo(std::string_view path) const
579{
580 const TKey *key = GetTKey(path);
581 if (!key)
582 return {};
583
584 RKeyInfo keyInfo(*key);
585 return keyInfo;
586}
587
589{
590 const auto nameCycle = std::string(key.GetPath()) + ";" + std::to_string(key.GetCycle());
591 void *obj = file.GetUntyped(nameCycle, key.GetClassName().c_str());
592 return obj;
593}
594
596{
597 return file.fFile.get();
598}
599
#define R__FAIL(msg)
Short-hand to return an RResult<T> in an error state; the RError is implicitly converted into RResult...
Definition RError.hxx:322
static const char * ToString(ENameCycleError err)
Definition RFile.cxx:51
static ENameCycleError DecodeNumericCycle(const char *str, std::optional< std::int16_t > &out)
Definition RFile.cxx:58
static void EnsureFileOpenAndBinary(const TFile *tfile, std::string_view path)
Definition RFile.cxx:173
static std::string ReconstructFullKeyPath(const TKey &key)
Definition RFile.cxx:182
static RNameCycleResult DecodeNameCycle(std::string_view nameCycleRaw)
Definition RFile.cxx:76
static std::string ValidateAndNormalizePath(std::string &path)
This function first validates, then normalizes the given path in place.
Definition RFile.cxx:129
#define R__LOG_ERROR(...)
Definition RLogger.hxx:356
#define R__LOG_INFO(...)
Definition RLogger.hxx:358
#define b(i)
Definition RSha256.hxx:100
#define a(i)
Definition RSha256.hxx:99
const char Option_t
Option string (const char)
Definition RtypesCore.h:81
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 result
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 UChar_t len
Option_t Option_t TPoint TPoint const char mode
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
char name[80]
Definition TGX11.cxx:142
Base class for all ROOT issued exceptions.
Definition RError.hxx:78
RIterator(TIterator *iter, Pattern_t pattern, std::uint32_t flags)
Definition RFile.cxx:424
std::deque< RIterStackElem > fIterStack
Definition RFile.hxx:150
std::string Pattern_t
Definition RFile.hxx:124
RIterator end() const
Definition RFile.cxx:448
RIterator begin() const
Definition RFile.cxx:443
std::uint32_t fFlags
Definition RFile.hxx:128
An interface to read from, or write to, a ROOT file, as well as performing other common operations.
Definition RFile.hxx:254
void Close()
Flushes the RFile if needed and closes it, disallowing any further reading or writing.
Definition RFile.cxx:559
static constexpr int kMaxPathNesting
Definition RFile.hxx:329
static std::unique_ptr< RFile > Open(std::string_view path, const ROpenOptions &opts=ROpenOptions())
Opens the file for reading.
Definition RFile.cxx:205
void PutUntyped(std::string_view path, const std::type_info &type, const void *obj, std::uint32_t flags, std::string_view title)
Writes obj to file, without taking its ownership.
Definition RFile.cxx:342
std::unique_ptr< TFile > fFile
Definition RFile.hxx:266
size_t Flush()
Writes all objects and the file structure to disk.
Definition RFile.cxx:554
void Print(std::ostream &out=std::cout) const
Prints the internal structure of this RFile to the given stream.
Definition RFile.cxx:540
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:242
void * GetUntyped(std::string_view path, std::variant< const char *, std::reference_wrapper< const std::type_info > > type) const
Gets object path from the file and returns an owning pointer to it.
Definition RFile.cxx:287
static std::unique_ptr< RFile > Recreate(std::string_view path, const RRecreateOptions &opts=RRecreateOptions())
Opens the file for reading/writing, overwriting it if it already exists.
Definition RFile.cxx:227
void Put(std::string_view path, const T &obj, std::string_view title="")
Puts object obj into the file and gives it a title.
Definition RFile.hxx:375
@ kListRecursive
Definition RFile.hxx:295
@ kPutFlag_AllowOverwrite
When encountering an object at the specified path, overwrite it with the new one instead of erroring ...
Definition RFile.hxx:261
@ kPutFlag_OverwriteKeepCycle
When overwriting an object, preserve the existing one and create a new cycle, rather than removing it...
Definition RFile.hxx:263
std::optional< RKeyInfo > GetKeyInfo(std::string_view path) const
Retrieves information about the key of object at path, if one exists.
Definition RFile.cxx:578
RFile(std::unique_ptr< TFile > file)
Definition RFile.cxx:238
static std::unique_ptr< RFile > Update(std::string_view path, const RUpdateOptions &opts=RUpdateOptions())
Opens the file for updating, creating a new one if it doesn't exist.
Definition RFile.cxx:216
Information about an RFile object's Key.
Definition RFile.hxx:71
std::string fTitle
Definition RFile.hxx:84
RKeyInfo()=default
std::uint16_t GetCycle() const
Definition RFile.hxx:105
const std::string & GetPath() const
Returns the absolute path of this key, i.e. the directory part plus the object name.
Definition RFile.hxx:100
std::uint16_t fCycle
Definition RFile.hxx:86
const std::string & GetClassName() const
Definition RFile.hxx:104
std::string fPath
Definition RFile.hxx:83
std::string fClassName
Definition RFile.hxx:85
ECategory fCategory
Definition RFile.hxx:87
A log configuration for a channel, e.g.
Definition RLogger.hxx:97
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition TClass.h:84
ROOT::DirAutoAdd_t GetDirectoryAutoAdd() const
Return the wrapper around the directory auto add function.
Definition TClass.cxx:7727
Bool_t InheritsFrom(const char *cl) const override
Return kTRUE if this class inherits from a class with name "classname".
Definition TClass.cxx:4995
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
Definition TClass.cxx:2999
A ROOT file is structured in Directories (like a file system).
TList * GetListOfKeys() const override
TDirectory::TContext keeps track and restore the current directory.
Definition TDirectory.h:89
Describe directory structure in memory.
Definition TDirectory.h:45
static TClass * Class()
virtual TDirectory * GetDirectory(const char *namecycle, Bool_t printError=false, const char *funcname="GetDirectory")
Find a directory using apath.
virtual TKey * GetKey(const char *, Short_t=9999) const
Definition TDirectory.h:222
virtual TKey * FindKey(const char *) const
Definition TDirectory.h:198
virtual TDirectory * mkdir(const char *name, const char *title="", Bool_t returnExistingDirectory=kFALSE)
Create a sub-directory "a" or a hierarchy of sub-directories "a/b/c/...".
virtual TList * GetListOfKeys() const
Definition TDirectory.h:224
TDirectory * GetMotherDir() const
Definition TDirectory.h:226
A file, usually with extension .root, that stores data and code in the form of serialized objects in ...
Definition TFile.h:130
Bool_t IsBinary() const
Definition TFile.h:347
Bool_t IsRaw() const
Definition TFile.h:348
Int_t Write(const char *name=nullptr, Int_t opt=0, Int_t bufsize=0) override
Write memory objects to this file.
Definition TFile.cxx:2503
virtual Bool_t IsArchive() const
Definition TFile.h:346
static TFile * Open(const char *name, Option_t *option="", const char *ftitle="", Int_t compress=ROOT::RCompressionSetting::EDefaults::kUseCompiledDefault, Int_t netopt=0)
Create / open a file.
Definition TFile.cxx:3802
Iterator abstract base class.
Definition TIterator.h:30
Book space in a file, create I/O buffers, to fill them, (un)compress them.
Definition TKey.h:28
const char * GetTitle() const override
Returns title (title can contain 32x32 xpm thumbnail/icon).
Definition TKey.cxx:1686
virtual const char * GetClassName() const
Definition TKey.h:77
virtual void * ReadObjectAny(const TClass *expectedClass)
To read an object (non deriving from TObject) from the file.
Definition TKey.cxx:1051
TDirectory * GetMotherDir() const
Definition TKey.h:87
Short_t GetCycle() const
Return cycle number associated to this key.
Definition TKey.cxx:631
TIterator * MakeIterator(Bool_t dir=kIterForward) const override
Return a list iterator.
Definition TList.cxx:852
The TNamed class is the base class for all named ROOT classes.
Definition TNamed.h:29
const char * GetName() const override
Returns name of object.
Definition TNamed.h:49
const char * GetTitle() const override
Returns title of object.
Definition TNamed.h:50
Mother of all ROOT objects.
Definition TObject.h:42
R__ALWAYS_INLINE Bool_t IsZombie() const
Definition TObject.h:161
virtual TClass * IsA() const
Definition TObject.h:248
std::pair< std::string_view, std::string_view > DecomposePath(std::string_view path)
Given a "path-like" string (like foo/bar/baz), returns a pair { dirName, baseName }.
Definition RFile.cxx:194
ROOT::RLogChannel & RFileLog()
Definition RFile.cxx:25
void * RFile_GetObjectFromKey(RFile &file, const RKeyInfo &key)
Returns an owning pointer to the object referenced by key.
Definition RFile.cxx:588
const char * ToString(ENTupleMergingMode mode)
void MarkTObjectAsNotOnHeap(TObject &obj)
Definition TObject.cxx:1277
TFile * GetRFileTFile(RFile &rfile)
Definition RFile.cxx:595
std::string Join(const std::string &sep, InputIt_t begin, InputIt_t end)
Concatenate a list of strings with a separator.
bool StartsWith(std::string_view string, std::string_view prefix)
std::vector< std::string > Split(std::string_view str, std::string_view delims, bool skipEmpty=false)
Splits a string at each character in delims.
RIterStackElem(TIterator *it, const std::string &path="")
Definition RFile.cxx:417
bool fEnableBrowsability
If true the RFile will show up in the TBrowser window.
Definition RFile.hxx:315
int fCompressionSettings
See core/zip/inc/Compression.h for the meaning of the compression argument.
Definition RFile.hxx:304
bool fEnableBrowsability
If true the RFile will show up in the TBrowser window.
Definition RFile.hxx:307
bool fEnableBrowsability
If true the RFile will show up in the TBrowser window.
Definition RFile.hxx:323