35enum class ENameCycleError {
44struct RNameCycleResult {
46 std::optional<std::int16_t> fCycle;
47 ENameCycleError fError;
51static const char *
ToString(ENameCycleError err)
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)];
63 return ENameCycleError::kInvalidSyntax;
64 if (res * 10 > std::numeric_limits<std::int16_t>::max())
65 return ENameCycleError::kCycleTooLarge;
70 assert(res < std::numeric_limits<std::int16_t>::max());
71 out =
static_cast<std::int16_t
>(res);
73 return ENameCycleError::kNoError;
80 if (nameCycleRaw.empty())
84 std::size_t semicolonIdx = nameCycleRaw.find_first_of(
';');
86 if (semicolonIdx == 0) {
87 result.fError = ENameCycleError::kNameEmpty;
92 if (nameCycleRaw.substr(semicolonIdx + 1).find_first_of(
';') != std::string_view::npos) {
93 result.fError = ENameCycleError::kInvalidSyntax;
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;
134 return "path cannot be empty";
136 if (path.back() ==
'/')
137 return "path cannot end with a '/'";
140 for (
char ch : path) {
143 valid &= !(ch < 33 || ch ==
'.');
146 return "path cannot contain control characters, whitespaces or dots";
153 const auto len = path.length();
154 while (nToStrip <
len && path[nToStrip] ==
'/')
158 path.erase(0, nToStrip);
162 const auto it = std::unique(path.begin(), path.end(), [](
char a,
char b) { return (a ==
'/' && b ==
'/'); });
163 path.erase(it, path.end());
166 const auto nesting = std::count(path.begin(), path.end(),
'/');
168 return "pathView contains too many levels of nesting";
184 std::string path = key.
GetName();
187 path = std::string(parent->
GetName()) +
"/" + path;
196 auto lastSlashIdx = path.rfind(
'/');
197 if (lastSlashIdx == std::string_view::npos)
200 auto dirName = path.substr(0, lastSlashIdx + 1);
201 auto pathName = path.substr(lastSlashIdx + 1);
202 return {dirName, pathName};
209 auto tfile = std::unique_ptr<TFile>(
TFile::Open(std::string(path).c_str(),
mode));
212 auto rfile = std::unique_ptr<RFile>(
new RFile(std::move(tfile)));
220 auto tfile = std::unique_ptr<TFile>(
TFile::Open(std::string(path).c_str(),
mode));
223 auto rfile = std::unique_ptr<RFile>(
new RFile(std::move(tfile)));
234 auto rfile = std::unique_ptr<RFile>(
new RFile(std::move(tfile)));
247 std::string fullPath = std::string(path);
248 char *dirName = fullPath.data();
249 char *restOfPath = strchr(dirName,
'/');
263 dirName = restOfPath;
264 restOfPath = strchr(restOfPath,
'/');
275 if (res.fError != ENameCycleError::kAnyCycle) {
276 if (res.fError != ENameCycleError::kNoError) {
279 }
else if (res.fCycle && *res.fCycle != key->
GetCycle()) {
288 std::variant<
const char *, std::reference_wrapper<const std::type_info>>
type)
const
293 std::string pathStr{path};
297 TClass *operator()(std::reference_wrapper<const std::type_info> ty) {
return TClass::GetClass(ty.get()); }
299 const TClass *cls = std::visit(std::move(typeVisitor),
type);
315 autoAddFunc(obj,
fFile.get());
321 autoAddFunc(obj,
nullptr);
326 <<
" but that path contains an object of type " << key->
GetClassName();
334 if (strchr(namedObj.
GetName(),
'/')) {
336 "' given to RFile::Put cannot have '/' in its name!"));
338 std::string completePath = (dirPath.empty() ?
"" : std::string(dirPath) +
'/') + namedObj.
GetName();
343 std::string_view title)
349 std::string path{pathSV};
353 if (path.find_first_of(
';') != std::string_view::npos) {
355 R__FAIL(
"Invalid object path '" + path +
356 "': character ';' is used to specify an object cycle, which only makes sense when reading."));
362 if (!
fFile->IsWritable())
372 const auto FullPathUntil = [&tokens](
auto idx) {
373 return ROOT::Join(
"/", std::span<const std::string>{tokens.data(), idx + 1});
376 for (
auto tokIdx = 0u; tokIdx < tokens.size() - 1; ++tokIdx) {
381 const TKey *existing = dir->
GetKey(tokens[tokIdx].c_str());
382 if (existing && strcmp(existing->
GetClassName(),
"TDirectory") != 0 &&
383 strcmp(existing->
GetClassName(),
"TDirectoryFile") != 0) {
385 FullPathUntil(tokIdx) +
"': name already taken by an object of type '" +
388 dir = dir->
mkdir(tokens[tokIdx].c_str(),
"",
true);
397 if (!allowOverwrite) {
398 const TKey *existing = dir->
GetKey(tokens[tokens.size() - 1].c_str());
403 }
else if (!backupCycle) {
404 writeOpts =
"WriteDelete";
407 const char *objName = tokens[tokens.size() - 1].c_str();
410 static_cast<TDirectoryFile *
>(dir)->WriteObjectAny(obj, cls, {objName, std::string(title).c_str()}, writeOpts);
418 : fIter(it), fDirPath(path)
430 if (!pattern.empty()) {
463 while (!fIterStack.empty()) {
464 auto &[iter, dirPath] = fIterStack.back();
466 TObject *keyObj = iter->Next();
469 fIterStack.pop_back();
473 assert(keyObj->
IsA() == TClass::GetClass<TKey>());
474 auto key =
static_cast<TKey *
>(keyObj);
476 const std::string dirSep = (dirPath.empty() ?
"" :
"/");
483 fIterStack.emplace_back(innerIter, dirPath + dirSep + dir->
GetName());
486 }
else if (!includeObj) {
491 const std::string &fullPath = dirPath + dirSep + key->GetName();
492 assert(!fIterStack.empty());
493 const std::size_t nesting = fIterStack.size() - 1;
505 if (!recursive && nesting != fRootDirNesting &&
506 (!isDir || nesting !=
static_cast<std::size_t
>(fRootDirNesting + 1)))
510 assert(!fullPath.empty());
518 if (fIterStack.empty())
521 const TKey *key = fCurKey;
527 const auto &dirPath = fIterStack.back().fDirPath;
531 keyInfo.
fPath = dirPath;
533 keyInfo.
fPath += std::string(dirPath.empty() ?
"" :
"/") + key->
GetName();
542 std::vector<RKeyInfo> keys;
543 auto keysIter = ListKeys();
544 for (
const auto &key : keysIter) {
545 keys.emplace_back(key);
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";
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())
590 const auto nameCycle = std::string(key.
GetPath()) +
";" + std::to_string(key.
GetCycle());
597 return file.
fFile.get();
#define R__FAIL(msg)
Short-hand to return an RResult<T> in an error state; the RError is implicitly converted into RResult...
static const char * ToString(ENameCycleError err)
static ENameCycleError DecodeNumericCycle(const char *str, std::optional< std::int16_t > &out)
static void EnsureFileOpenAndBinary(const TFile *tfile, std::string_view path)
static std::string ReconstructFullKeyPath(const TKey &key)
static RNameCycleResult DecodeNameCycle(std::string_view nameCycleRaw)
static std::string ValidateAndNormalizePath(std::string &path)
This function first validates, then normalizes the given path in place.
#define R__LOG_ERROR(...)
const char Option_t
Option string (const char)
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
Base class for all ROOT issued exceptions.
RIterator(TIterator *iter, Pattern_t pattern, std::uint32_t flags)
std::uint16_t fRootDirNesting
std::deque< RIterStackElem > fIterStack
An interface to read from, or write to, a ROOT file, as well as performing other common operations.
void Close()
Flushes the RFile if needed and closes it, disallowing any further reading or writing.
static constexpr int kMaxPathNesting
static std::unique_ptr< RFile > Open(std::string_view path, const ROpenOptions &opts=ROpenOptions())
Opens the file for reading.
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.
std::unique_ptr< TFile > fFile
size_t Flush()
Writes all objects and the file structure to disk.
void Print(std::ostream &out=std::cout) const
Prints the internal structure of this RFile to the given stream.
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...
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.
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.
void Put(std::string_view path, const T &obj, std::string_view title="")
Puts object obj into the file and gives it a title.
@ kPutFlag_AllowOverwrite
When encountering an object at the specified path, overwrite it with the new one instead of erroring ...
@ kPutFlag_OverwriteKeepCycle
When overwriting an object, preserve the existing one and create a new cycle, rather than removing it...
std::optional< RKeyInfo > GetKeyInfo(std::string_view path) const
Retrieves information about the key of object at path, if one exists.
RFile(std::unique_ptr< TFile > file)
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.
Information about an RFile object's Key.
std::uint16_t GetCycle() const
const std::string & GetPath() const
Returns the absolute path of this key, i.e. the directory part plus the object name.
const std::string & GetClassName() const
A log configuration for a channel, e.g.
TClass instances represent classes, structs and namespaces in the ROOT type system.
ROOT::DirAutoAdd_t GetDirectoryAutoAdd() const
Return the wrapper around the directory auto add function.
Bool_t InheritsFrom(const char *cl) const override
Return kTRUE if this class inherits from a class with name "classname".
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.
A ROOT file is structured in Directories (like a file system).
TList * GetListOfKeys() const override
TDirectory::TContext keeps track and restore the current directory.
Describe directory structure in memory.
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
virtual TKey * FindKey(const char *) const
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
TDirectory * GetMotherDir() const
A file, usually with extension .root, that stores data and code in the form of serialized objects in ...
Int_t Write(const char *name=nullptr, Int_t opt=0, Int_t bufsize=0) override
Write memory objects to this file.
virtual Bool_t IsArchive() const
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.
Iterator abstract base class.
Book space in a file, create I/O buffers, to fill them, (un)compress them.
const char * GetTitle() const override
Returns title (title can contain 32x32 xpm thumbnail/icon).
virtual const char * GetClassName() const
virtual void * ReadObjectAny(const TClass *expectedClass)
To read an object (non deriving from TObject) from the file.
TDirectory * GetMotherDir() const
Short_t GetCycle() const
Return cycle number associated to this key.
TIterator * MakeIterator(Bool_t dir=kIterForward) const override
Return a list iterator.
The TNamed class is the base class for all named ROOT classes.
const char * GetName() const override
Returns name of object.
const char * GetTitle() const override
Returns title of object.
Mother of all ROOT objects.
R__ALWAYS_INLINE Bool_t IsZombie() const
virtual TClass * IsA() const
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 }.
ROOT::RLogChannel & RFileLog()
void * RFile_GetObjectFromKey(RFile &file, const RKeyInfo &key)
Returns an owning pointer to the object referenced by key.
const char * ToString(ENTupleMergingMode mode)
void MarkTObjectAsNotOnHeap(TObject &obj)
TFile * GetRFileTFile(RFile &rfile)
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="")
bool fEnableBrowsability
If true the RFile will show up in the TBrowser window.
int fCompressionSettings
See core/zip/inc/Compression.h for the meaning of the compression argument.
bool fEnableBrowsability
If true the RFile will show up in the TBrowser window.
bool fEnableBrowsability
If true the RFile will show up in the TBrowser window.