34enum class ENameCycleError {
43struct RNameCycleResult {
45 std::optional<std::int16_t> fCycle;
46 ENameCycleError fError;
50static const char *
ToString(ENameCycleError err)
52 static const char *
const kErrorStr[] = {
"",
"",
"invalid syntax",
"cycle is too large",
"name is empty"};
53 static_assert(std::size(kErrorStr) ==
static_cast<std::size_t
>(ENameCycleError::kCOUNT));
54 return kErrorStr[
static_cast<std::size_t
>(err)];
62 return ENameCycleError::kInvalidSyntax;
63 if (res * 10 > std::numeric_limits<std::int16_t>::max())
64 return ENameCycleError::kCycleTooLarge;
69 assert(res < std::numeric_limits<std::int16_t>::max());
70 out =
static_cast<std::int16_t
>(res);
72 return ENameCycleError::kNoError;
79 if (nameCycleRaw.empty())
83 std::size_t semicolonIdx = nameCycleRaw.find_first_of(
';');
85 if (semicolonIdx == 0) {
86 result.fError = ENameCycleError::kNameEmpty;
91 if (nameCycleRaw.substr(semicolonIdx + 1).find_first_of(
';') != std::string_view::npos) {
92 result.fError = ENameCycleError::kInvalidSyntax;
96 result.fName = nameCycleRaw.substr(0, semicolonIdx);
97 if (semicolonIdx < std::string_view::npos) {
98 if (semicolonIdx == nameCycleRaw.length() - 1 && nameCycleRaw[semicolonIdx] ==
'*')
99 result.fError = ENameCycleError::kAnyCycle;
133 return "path cannot be empty";
135 if (path.back() ==
'/')
136 return "path cannot end with a '/'";
139 for (
char ch : path) {
142 valid &= !(ch < 33 || ch ==
'.');
145 return "path cannot contain control characters, whitespaces or dots";
152 const auto len = path.length();
153 while (nToStrip <
len && path[nToStrip] ==
'/')
157 path.erase(0, nToStrip);
161 const auto it = std::unique(path.begin(), path.end(), [](
char a,
char b) { return (a ==
'/' && b ==
'/'); });
162 path.erase(it, path.end());
165 const auto nesting = std::count(path.begin(), path.end(),
'/');
166 if (nesting > RFile::kMaxPathNesting)
167 return "pathView contains too many levels of nesting";
183 std::string path = key.
GetName();
186 path = std::string(parent->
GetName()) +
"/" + path;
195 auto lastSlashIdx = path.rfind(
'/');
196 if (lastSlashIdx == std::string_view::npos)
199 auto dirName = path.substr(0, lastSlashIdx + 1);
200 auto pathName = path.substr(lastSlashIdx + 1);
201 return {dirName, pathName};
204std::unique_ptr<RFile> RFile::Open(std::string_view path,
const ROpenOptions &opts)
208 auto tfile = std::unique_ptr<TFile>(
TFile::Open(std::string(path).c_str(),
mode));
211 auto rfile = std::unique_ptr<RFile>(
new RFile(std::move(tfile)));
219 auto tfile = std::unique_ptr<TFile>(
TFile::Open(std::string(path).c_str(),
mode));
222 auto rfile = std::unique_ptr<RFile>(
new RFile(std::move(tfile)));
233 auto rfile = std::unique_ptr<RFile>(
new RFile(std::move(tfile)));
246 std::string fullPath = std::string(path);
247 char *dirName = fullPath.data();
248 char *restOfPath = strchr(dirName,
'/');
262 dirName = restOfPath;
263 restOfPath = strchr(restOfPath,
'/');
274 if (res.fError != ENameCycleError::kAnyCycle) {
275 if (res.fError != ENameCycleError::kNoError) {
278 }
else if (res.fCycle && *res.fCycle != key->
GetCycle()) {
287 std::variant<
const char *, std::reference_wrapper<const std::type_info>>
type)
const
292 std::string pathStr{path};
296 TClass *operator()(std::reference_wrapper<const std::type_info> ty) {
return TClass::GetClass(ty.get()); }
298 const TClass *cls = std::visit(std::move(typeVisitor),
type);
314 autoAddFunc(obj,
fFile.get());
320 autoAddFunc(obj,
nullptr);
325 <<
" but that path contains an object of type " << key->
GetClassName();
332 std::string_view title)
338 std::string path{pathSV};
342 if (path.find_first_of(
';') != std::string_view::npos) {
344 R__FAIL(
"Invalid object path '" + path +
345 "': character ';' is used to specify an object cycle, which only makes sense when reading."));
351 if (!
fFile->IsWritable())
361 const auto FullPathUntil = [&tokens](
auto idx) {
362 return ROOT::Join(
"/", std::span<const std::string>{tokens.data(), idx + 1});
365 for (
auto tokIdx = 0u; tokIdx < tokens.size() - 1; ++tokIdx) {
370 const TKey *existing = dir->
GetKey(tokens[tokIdx].c_str());
371 if (existing && strcmp(existing->
GetClassName(),
"TDirectory") != 0 &&
372 strcmp(existing->
GetClassName(),
"TDirectoryFile") != 0) {
374 FullPathUntil(tokIdx) +
"': name already taken by an object of type '" +
377 dir = dir->
mkdir(tokens[tokIdx].c_str(),
"",
true);
386 if (!allowOverwrite) {
387 const TKey *existing = dir->
GetKey(tokens[tokens.size() - 1].c_str());
392 }
else if (!backupCycle) {
393 writeOpts =
"WriteDelete";
396 const char *objName = tokens[tokens.size() - 1].c_str();
399 static_cast<TDirectoryFile *
>(dir)->WriteObjectAny(obj, std::string(title).c_str(), cls, objName, writeOpts);
407 : fIter(it), fDirPath(path)
419 if (!pattern.empty()) {
452 while (!fIterStack.empty()) {
453 auto &[iter, dirPath] = fIterStack.back();
455 TObject *keyObj = iter->Next();
458 fIterStack.pop_back();
462 assert(keyObj->
IsA() == TClass::GetClass<TKey>());
463 auto key =
static_cast<TKey *
>(keyObj);
465 const std::string dirSep = (dirPath.empty() ?
"" :
"/");
472 fIterStack.emplace_back(innerIter, dirPath + dirSep + dir->
GetName());
475 }
else if (!includeObj) {
480 const std::string &fullPath = dirPath + dirSep + key->GetName();
481 assert(!fIterStack.empty());
482 const std::size_t nesting = fIterStack.size() - 1;
494 if (!recursive && nesting != fRootDirNesting &&
495 (!isDir || nesting !=
static_cast<std::size_t
>(fRootDirNesting + 1)))
499 assert(!fullPath.empty());
507 if (fIterStack.empty())
510 const TKey *key = fCurKey;
516 const auto &dirPath = fIterStack.back().fDirPath;
520 keyInfo.
fPath = dirPath;
522 keyInfo.
fPath += std::string(dirPath.empty() ?
"" :
"/") + key->
GetName();
531 std::vector<RKeyInfo> keys;
532 auto keysIter = ListKeys();
533 for (
const auto &key : keysIter) {
534 keys.emplace_back(key);
537 std::sort(keys.begin(), keys.end(), [](
const auto &
a,
const auto &
b) { return a.GetPath() < b.GetPath(); });
538 for (
const auto &key : keys) {
539 out << key.GetClassName() <<
" " << key.GetPath() <<
";" << key.GetCycle() <<
": \"" << key.GetTitle() <<
"\"\n";
556 fTitle(key.GetTitle()),
557 fClassName(key.GetClassName()),
558 fCycle(key.GetCycle()),
559 fLenObj(key.GetObjlen()),
560 fNBytesObj(key.GetNbytes() - key.GetKeylen()),
561 fNBytesKey(key.GetKeylen()),
562 fSeekKey(key.GetSeekKey()),
563 fSeekParentDir(key.GetSeekPdir())
579 const auto nameCycle = std::string(key.
GetPath()) +
";" + std::to_string(key.
GetCycle());
586 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.
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.
@ 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.
const char * GetName() const override
Returns name 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.