105 std::string nnn = objname;
110 while ((pos = nnn.find_first_of(
"- []<>#:&?/\'\"\\")) != std::string::npos)
111 nnn.replace(pos, 1,
"_");
113 itemname = nnn.c_str();
117 itemname.
Form(
"%s_%d", nnn.c_str(), cnt++);
233 "When member specified, pointer on object (not member) should be provided; use SetFoundResult");
312 if (obj && !obj_name)
316 if (!obj_name || (*obj_name == 0))
319 const char *full_name =
nullptr;
323 const char *
slash = strrchr(obj_name,
'/');
325 full_name = obj_name;
326 obj_name = slash + 1;
368 while (*separ ==
'/') {
424 :
TNamed(name,
"sniffer of root objects"), fObjectsPath(objpath)
468 const char *rslash = strrchr(path,
'/');
471 if ((rslash == 0) || (*rslash == 0))
501 if (!item_name || (*item_name == 0) || !
fCurrentArg)
516 if (!username || !option || (*option == 0))
519 if (strcmp(option,
"all") == 0)
522 if (strcmp(username, option) == 0)
525 if (strstr(option, username) == 0)
534 return find ? 2 : -1;
548 if (!full_item_name || (*full_item_name == 0))
551 const char *item_name = strrchr(full_item_name,
'/');
554 if ((item_name == 0) || (*item_name == 0))
555 item_name = full_item_name;
560 const char *options =
nullptr;
564 while ((obj = iter()) !=
nullptr) {
565 const char *title = obj->
GetTitle();
567 if (strstr(title, pattern1.
Data()) == title) {
568 options = title + pattern1.
Length();
571 if (strstr(title, pattern2.
Data()) == title) {
572 options = title + pattern2.
Length();
611 if (!cl || !ptr || rec.
Done())
621 while ((obj = iter()) !=
nullptr) {
623 if (!rdata || strchr(rdata->
GetName(),
'.'))
633 member_ptr = *((
char **)member_ptr);
637 if (chld.
GoInside(rec, member, 0,
this)) {
642 if (coll_offset >= 0) {
650 const char *title = member->
GetTitle();
651 if ((title != 0) && (strlen(title) != 0))
679 if (coll_offset >= 0) {
702 TClass *cl = obj ? obj->IsA() :
nullptr;
704 const char *pos = strstr(cl ? cl->
GetTitle() :
"",
"*SNIFF*");
715 const char *pos0 = pos;
716 while ((*pos != 0) && (*pos !=
'='))
722 Bool_t quotes = (*pos ==
'\"');
727 while ((*pos != 0) && (*pos != (quotes ?
'\"' :
' ')))
729 TString value(pos0, pos - pos0);
743 if (strcmp(key->
GetClassName(),
"TDirectoryFile") == 0) {
748 obj_class = dir->IsA();
780 if ((!lst || (lst->
GetSize() == 0)) && (!keys_lst || (keys_lst->
GetSize() == 0)))
785 if (!folderrec.
GoInside(rec,
nullptr, foldername,
this))
809 if (!chld.
GoInside(master, obj,
nullptr,
this)) {
821 while ((next = iter()) !=
nullptr) {
847 TIter iter(keys_lst);
850 while ((kobj = iter()) !=
nullptr) {
851 TKey *key =
dynamic_cast<TKey *
>(kobj);
874 if (chld.
GoInside(master, obj, fullname.
Data(),
this)) {
879 if (chld.
SetResult(keyobj, keyobj->IsA()))
886 TClass *obj_class = obj->IsA();
933 if (chld.
GoInside(rec,
nullptr,
"StreamerInfo",
this)) {
937 chld.
SetField(
"_after_request",
"JSROOT.MarkAsStreamerInfo");
1010 if (res_member && res_cl && !member) {
1016 res = *((
char **)res);
1025 *member = res_member;
1063 TClass *obj_cl =
nullptr;
1074 TClass *obj_cl =
nullptr;
1077 return res && (obj_chld > 0);
1089 const char *path_ = path.c_str();
1100 TClass *obj_cl =
nullptr;
1103 if (!obj_ptr || (!obj_cl && !member))
1110 return !res.empty();
1122 if ((kind == 0) || (strcmp(kind,
"Command") != 0)) {
1124 Info(
"ExecuteCmd",
"Entry %s is not a command", path.c_str());
1129 const char *cmethod =
GetItemField(parent, obj,
"method");
1130 if (!cmethod || (strlen(cmethod) == 0)) {
1132 Info(
"ExecuteCmd",
"Entry %s do not defines method for execution", path.c_str());
1142 Info(
"ExecuteCmd",
"Entry %s not allowed for specified user", path.c_str());
1150 const char *cnumargs =
GetItemField(parent, obj,
"_numargs");
1157 for (
Int_t n = 0;
n < numargs;
n++) {
1162 Info(
"ExecuteCmd",
"For command %s argument %s not specified in options %s", path.c_str(), argname.
Data(),
1175 Info(
"ExecuteCmd",
"Executing command %s method:%s", path.c_str(), method.
Data());
1180 if (method.
Index(
"this->") == 0) {
1184 }
else if (separ !=
kNPOS) {
1190 TString::Format(
"((%s*)%lu)->%s", item_obj->ClassName(), (
long unsigned)item_obj, method.
Data() + separ + 3);
1192 Info(
"ExecuteCmd",
"Executing %s", method.
Data());
1197 res = std::to_string(v);
1217 return !res.empty();
1235 if (!value || (strlen(value) == 0))
1249 if (remove_quotes && (res.
Length() > 1) && ((res[0] ==
'\'') || (res[0] ==
'\"')) &&
1250 (res[0] == res[res.
Length() - 1])) {
1301 std::vector<std::string> mem;
1306 for (
Int_t n = 0;
n < number;
n++) {
1307 const char *next = args;
1308 while ((next < ends) && (*next !=
'\n'))
1311 Error(
"ProduceMulti",
"Not enough arguments in POST block");
1315 std::string file1(args, next - args);
1318 std::string path1, opt1;
1321 std::size_t pos = file1.find_first_of(
'?');
1322 if (pos != std::string::npos) {
1323 opt1 = file1.substr(pos + 1, file1.length() - pos);
1328 pos = file1.find_last_of(
'/');
1329 if (pos != std::string::npos) {
1330 path1 = file1.substr(0, pos);
1331 file1.erase(0, pos + 1);
1335 path1 = path +
"/" + path1;
1340 Produce(path1, file1, opt1, res1);
1350 mem.emplace_back(std::move(res1));
1358 for (
unsigned n = 0;
n < mem.size();
n++)
1359 length += 4 + mem[
n].length();
1361 char *curr = (
char *)str.data();
1362 for (
unsigned n = 0;
n < mem.size();
n++) {
1364 *curr++ = (char)(l & 0xff);
1366 *curr++ = (char)(l & 0xff);
1368 *curr++ = (char)(l & 0xff);
1370 *curr++ = (char)(l & 0xff);
1371 if (!mem[
n].empty())
1372 memcpy(curr, mem[
n].
data(), mem[
n].length());
1373 curr += mem[
n].length();
1433 Bool_t TRootSniffer::Produce(
const char *path,
const char *
file,
const char *options,
void *&ptr,
Long_t &length,
1437 if (!Produce(path,
file, options, data))
1439 if (strstr(
file,
".json") || strstr(
file,
".xml") || strstr(
file,
".txt")) {
1445 length = data.length();
1446 ptr =
malloc(length + 1);
1447 memcpy(ptr, data.data(), length + 1);
1468 Bool_t TRootSniffer::Produce(
const std::string &path,
const std::string &
file,
const std::string &options, std::string &res)
1473 if (
file ==
"root.bin")
1476 if (
file ==
"root.png")
1479 if (
file ==
"root.jpeg")
1482 if (
file ==
"root.gif")
1485 if (
file ==
"exe.bin")
1488 if (
file ==
"root.xml")
1491 if (
file ==
"root.json")
1495 if (
file ==
"exe.txt")
1498 if (
file ==
"exe.json")
1501 if (
file ==
"cmd.json")
1504 if (
file ==
"item.json")
1507 if (
file ==
"item.xml")
1510 if (
file ==
"multi.bin")
1513 if (
file ==
"multi.json")
1527 Error(
"RegisterObject",
"Not found top ROOT folder!!!");
1535 httpfold = topf->
AddFolder(
"http",
"ROOT http server");
1539 gROOT->GetListOfCleanups()->Add(httpfold);
1550 if (within_objects && ((path.
Length() == 0) || (path[0] !=
'/')))
1556 while (path.Tokenize(tok, from,
"/")) {
1565 while ((obj = iter()) !=
nullptr) {
1575 obj = fold->
AddFolder(tok,
"sub-folder");
1592 return dynamic_cast<TFolder *
>(
GetItem(subfolder, parent, force));
1642 Error(
"UnregisterObject",
"Not found //root/http folder!!!");
1687 Info(
"AccessField",
"Should be special case for top folder, support later");
1696 if (parent == chld) {
1697 last_find = find =
kTRUE;
1700 while ((obj = iter()) !=
nullptr) {
1702 if (last_find && obj->GetName() && !strcmp(name, obj->GetName()))
1705 last_find = (obj == chld);
1708 if (find && !last_find)
1719 return curr !=
nullptr;
1732 curr =
new TNamed(name, value);
1744 Error(
"AccessField",
"Fail cast to TList");
1761 if (!fullname || !name)
1767 if (!parent || !obj)
1786 if (!parent || !obj || !name)
1791 if (!
AccessField(parent, obj, name,
nullptr, &field))
1794 return field ? field->
GetTitle() :
nullptr;
1844 if (strncmp(icon,
"button;", 7) == 0) {
1855 if (strstr(method, nextname.
Data()) == 0)
1858 }
while (numargs < 100);
TString fItemName
! name of current item
Bool_t RegisterObject(const char *subfolder, TObject *obj)
Register object in subfolder structure subfolder parameter can have many levels like: ...
virtual const char * GetName() const
Returns name of object.
const char * item_prop_user
A TFolder object is a collection of objects and folders.
Bool_t GoInside(TRootSnifferScanRec &super, TObject *obj, const char *obj_name=nullptr, TRootSniffer *sniffer=nullptr)
Method verifies if new level of hierarchy should be started with provided object. ...
void ScanCollection(TRootSnifferScanRec &rec, TCollection *lst, const char *foldername=nullptr, TCollection *keys_lst=nullptr)
scan collection content
Bool_t CanExploreItem(const char *path)
Method returns true when object has childs or one could try to expand item.
virtual TList * GetListOfKeys() const
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
virtual ULong_t GetItemHash(const char *itemname)
Get hash function for specified item used to detect any changes in the specified object.
Bool_t IsItemField(TObject *obj) const
return true when object is TNamed with kItemField bit set such objects used to keep field values for ...
UInt_t fMask
! defines operation kind
virtual Bool_t ProduceImage(Int_t kind, const std::string &path, const std::string &options, std::string &res)
Method to produce image from specified object.
void BeforeNextChild()
indicates that new child for current element will be started
TClass * GetResClass() const
Collectable string class.
Bool_t IsReadyForResult() const
Checks if result will be accepted.
Int_t CheckRestriction(const char *item_name)
Checked if restriction is applied to the item full_item_name should have full path to the item...
All ROOT classes may have RTTI (run time type identification) support added.
Storage of hierarchy scan in TRootSniffer in JSON format.
This class represents a WWW compatible URL.
TString & ReplaceAll(const TString &s1, const TString &s2)
virtual const char * GetClassName() const
virtual void SetOwner(Bool_t enable=kTRUE)
Set whether this collection is the owner (enable==true) of its content.
virtual Bool_t CanDrawClass(TClass *)
const char * GetAutoLoad() const
return name of configured autoload scripts (or 0)
const char * GetTypeName() const
Get type of data member, e,g.: "class TDirectory*" -> "TDirectory".
virtual void Remove(TObject *obj)
Remove object from this folder. obj must be a TObject or a TFolder.
virtual void AddFirst(TObject *obj)
Add object at the beginning of the list.
TString DecodeUrlOptionValue(const char *value, Bool_t remove_quotes=kTRUE)
method replaces all kind of special symbols, which could appear in URL options
Bool_t SetFoundResult(void *obj, TClass *cl, TDataMember *member=nullptr)
Set found element with class and datamember (optional)
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Bool_t HasRestriction(const char *item_name)
Made fast check if item with specified name is in restriction list If returns true, requires precise check with CheckRestriction() method.
R__EXTERN TVirtualMutex * gROOTMutex
virtual void BeforeNextChild(Int_t, Int_t, Int_t)
void Restrict(const char *path, const char *options)
Restrict access to the specified location.
Bool_t UnregisterObject(TObject *obj)
unregister (remove) object from folders structures folder itself will remain even when it will be emp...
#define ROOT_VERSION_CODE
Int_t fRestriction
! restriction 0 - default, 1 - read-only, 2 - full access
Abstract interface for storage of hierarchy scan in TRootSniffer.
TString fCurrentAllowedMethods
! list of allowed methods, extracted when analyzed object restrictions
Bool_t CreateItem(const char *fullname, const char *title)
create item element
UInt_t Hash(ECaseCompare cmp=kExact) const
Return hash value.
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
virtual TObject * FindObject(const char *name) const
Delete a TObjLink object.
if object in a list can be deleted
Bool_t SetResult(void *obj, TClass *cl, TDataMember *member=nullptr)
Obsolete, use SetFoundResult instead.
void CloseNode()
close started node
Bool_t CanExpandItem()
Returns true when item can be expanded.
const char * item_prop_rootversion
Int_t GetBaseClassOffset(const TClass *toBase, void *address=0, bool isDerivedObject=true)
Bool_t IsBasic() const
Return true if data member is a basic type, e.g. char, int, long...
Bool_t IsReadOnly(Bool_t dflt=kTRUE)
Returns read-only flag for current item.
virtual const char * ClassName() const
Returns name of class to which the object belongs.
mask for actions, only actions copied to child rec
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString...
virtual void ScanObjectChilds(TRootSnifferScanRec &rec, TObject *obj)
scans object childs (if any) here one scans collection, branches, trees and so on ...
Bool_t SetItemField(const char *fullname, const char *name, const char *value)
set field for specified item
THttpCallArg * fCurrentArg
! current http arguments (if any)
The TNamed class is the base class for all named ROOT classes.
virtual TObject * FindObject(const char *name) const
Find an object in this collection using its name.
Bool_t fReadOnly
! indicate if sniffer allowed to change ROOT structures - like read objects from file ...
Bool_t ScanOnlyFields() const
return true when only fields are scanned by the sniffer
Bool_t AccessField(TFolder *parent, TObject *item, const char *name, const char *value, TNamed **only_get=nullptr)
set or get field for the child each field coded as TNamed object, placed after chld in the parent hie...
Long_t Property() const
Get property description word. For meaning of bits see EProperty.
virtual void ScanKeyProperties(TRootSnifferScanRec &rec, TKey *key, TObject *&obj, TClass *&obj_class)
scans key properties in special cases load objects from the file
const char * item_prop_kind
virtual void * FindInHierarchy(const char *path, TClass **cl=nullptr, TDataMember **member=nullptr, Int_t *chld=nullptr)
Search element with specified path Returns pointer on element Optionally one could obtain element cla...
void Clear()
Clear string without changing its capacity.
Bool_t CanDrawItem(const char *path)
Method verifies if object can be drawn.
const char * item_prop_typename
TFolder * GetSubFolder(const char *foldername, Bool_t force=kFALSE)
creates subfolder where objects can be registered
TString & Append(const char *cs)
virtual void Add(TObject *obj)
Add object to this folder. obj must be a TObject or a TFolder.
Long_t GetThisOffset() const
const char * fSearchPath
! current path searched
const char * GetUserName() const
return authenticated user name (0 - when no authentication)
expand of specified item - allowed to scan object members
virtual void RecursiveRemove(TObject *obj)
Recursively remove object from a folder.
virtual TList * GetList() const
Book space in a file, create I/O buffers, to fill them, (un)compress them.
void SetRootClass(TClass *cl)
Mark item with ROOT class and correspondent streamer info.
const char * GetValueFromOptions(const char *key) const
Return a value for a given key from the URL options.
TFolder * AddFolder(const char *name, const char *title, TCollection *collection=0)
Create a new folder and add it to the list of folders of this folder, return a pointer to the created...
Int_t fNumChilds
! number of childs
virtual ~TRootSniffer()
destructor
TCollection * GetListOfFolders() const
Storage of hierarchy scan in TRootSniffer in XML format.
search for specified item (only objects and collections)
Int_t GetMaxIndex(Int_t dim) const
Return maximum index for array dimension "dim".
Int_t WithCurrentUserName(const char *option)
return 2 when option match to current user name return 1 when option==all return 0 when option does n...
Int_t GetResNumChilds() const
virtual Bool_t ExecuteCmd(const std::string &path, const std::string &options, std::string &res)
execute command marked as _kind=='Command'
void BuildRealData(void *pointer=0, Bool_t isTransient=kFALSE)
Build a full list of persistent data members.
Int_t GetResRestrict() const
const char * item_prop_arraydim
virtual Bool_t ProduceXml(const std::string &path, const std::string &options, std::string &res)
produce XML data for specified item For object conversion TBufferXML is used Implemented only in TRoo...
virtual Bool_t ProduceExe(const std::string &path, const std::string &options, Int_t reskind, std::string &res)
execute command for specified object options include method and extra list of parameters sniffer shou...
const char * item_prop_hidden
void SetResult(void *_res, TClass *_rescl, TDataMember *_resmemb, Int_t _res_chld, Int_t restr=0)
set pointer on found element, class and number of childs
const void * GetPostData() const
return pointer on posted with request data
TRootSniffer(const char *name, const char *objpath="Objects")
constructor
Int_t fLevel
! current level of hierarchy
const char * item_prop_realname
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
TDataMember * GetDataMember() const
Collection abstract base class.
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
const char * item_prop_title
virtual Bool_t ProduceJson(const std::string &path, const std::string &options, std::string &res)
produce JSON data for specified item For object conversion TBufferJSON is used
TString fObjectsPath
! default path for registered objects
Bool_t RegisterCommand(const char *cmdname, const char *method, const char *icon)
Register command which can be executed from web interface.
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
char * Form(const char *fmt,...)
virtual Bool_t ProduceBinary(const std::string &path, const std::string &options, std::string &res)
produce binary data for specified item if "zipped" option specified in query, buffer will be compress...
Int_t fNumFields
! number of fields
The TRealData class manages the effective list of all data members for a given class.
Int_t GetArrayDim() const
Return number of array dimensions.
The ROOT global object gROOT contains a list of all defined classes.
virtual void ScanRoot(TRootSnifferScanRec &rec)
scan complete ROOT objects hierarchy For the moment it includes objects in gROOT directory and list o...
virtual ~TRootSnifferScanRec()
destructor
Long_t Property() const
Set TObject::fBits and fStreamerType to cache information about the class.
void ScanHierarchy(const char *topname, const char *path, TRootSnifferStore *store, Bool_t only_fields=kFALSE)
Method scans normal objects, registered in ROOT.
if object destructor must call RecursiveRemove()
TString fAutoLoad
! scripts names, which are add as _autoload parameter to h.json request
void ScanObjectMembers(TRootSnifferScanRec &rec, TClass *cl, char *ptr)
scan object data members some members like enum or static members will be excluded ...
TRootSnifferScanRec()
constructor
const char * GetTrueTypeName() const
Get full type description of data member, e,g.: "class TDirectory*".
TString & Remove(Ssiz_t pos)
TList fItemsNames
! list of created items names, need to avoid duplication
check if there childs, very similar to search
TObjArray * Tokenize(const TString &delim) const
This function is used to isolate sequential tokens in a TString.
void BuildFullName(TString &buf, TRootSnifferScanRec *prnt=nullptr)
Produces full name for the current item.
TDataMember * GetResMember() const
TRootSnifferStore * fStore
! object to store results
Describe directory structure in memory.
virtual Bool_t ProduceMulti(const std::string &path, const std::string &options, std::string &res, Bool_t asjson=kTRUE)
Process several requests, packing all results into binary or JSON buffer Input parameters should be c...
TList * GetListOfRealData() const
TRootSnifferScanRec * fParent
! pointer on parent record
#define R__LOCKGUARD(mutex)
virtual void CreateNode(Int_t, const char *)
int CompareTo(const char *cs, ECaseCompare cmp=kExact) const
Compare a string to char *cs2.
void ParseOptions() const
Parse URL options into a key/value map.
virtual TObject * FindObject(const char *name) const
Search object identified by name in the tree of folders inside this folder.
Bool_t Done() const
Method indicates that scanning can be interrupted while result is set.
virtual void AddAfter(const TObject *after, TObject *obj)
Insert object after object after in the list.
Mother of all ROOT objects.
Int_t Depth() const
Returns depth of hierarchy.
virtual void SetField(Int_t, const char *, const char *, Bool_t)
Int_t IsSTLContainer()
The return type is defined in TDictionary (kVector, kList, etc.)
void SetField(const char *name, const char *value, Bool_t with_quotes=kTRUE)
Set item field only when creating is specified.
void SetAutoLoad(const char *scripts="")
When specified, _autoload attribute will be always add to top element of h.json/h.hml requests Used to instruct browser automatically load special code.
virtual const char * GetTitle() const
Returns title of object.
virtual TObject * ReadObj()
To read a TObject* from the file.
virtual void Add(TObject *obj)
const char * GetArrayIndex() const
If the data member is pointer and has a valid array size in its comments GetArrayIndex returns a stri...
Bool_t CanSetFields() const
return true when fields could be set to the hierarchy item
virtual void CloseNode(Int_t, Int_t)
void SetOptions(const char *opt)
Bool_t fHasMore
! indicates that potentially there are more items can be found
const char * item_prop_more
virtual Int_t GetLast() const
Returns index of last object in collection.
virtual Bool_t HasStreamerInfo() const
virtual TObject * FindObject(const char *name) const
Find an object in this collection using its name.
Int_t Atoi() const
Return integer value of string.
static TString ConvertToJSON(const TObject *obj, Int_t compact=0, const char *member_name=nullptr)
Converts object, inherited from TObject class, to JSON string Lower digit of compact parameter define...
Bool_t fNodeStarted
! indicate if node was started
const char * item_prop_autoload
if set, only fields for specified item will be set (but all fields)
Int_t GetIntValueFromOptions(const char *key) const
Return a value for a given key from the URL options as an Int_t, a missing key returns -1...
Short_t GetCycle() const
Return cycle number associated to this key.
virtual void ScanObjectProperties(TRootSnifferScanRec &rec, TObject *obj)
scans object properties here such fields as _autoload or _icon properties depending on class or objec...
virtual const char * GetName() const
Returns name of object.
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
void MakeItemName(const char *objname, TString &itemname)
Construct item name, using object name as basis.
virtual const char * GetName() const
Returns name of object.
void SetCurrentCallArg(THttpCallArg *arg)
set current http arguments, which then used in different process methods For instance, if user authorized with some user name, depending from restrictions some objects will be invisible or user get full access to the element
virtual void SetTitle(const char *title="")
Set the title of the TNamed.
Bool_t IsaPointer() const
Return true if data member is a pointer.
Long_t GetPostDataLength() const
return length of posted with request data
virtual Bool_t ProduceItem(const std::string &path, const std::string &options, std::string &res, Bool_t asjson=kTRUE)
produce JSON/XML for specified item contrary to h.json request, only fields for specified item are st...
Int_t fCurrentRestrict
! current restriction for last-found object
Bool_t IsScanGlobalDir() const
Returns true when sniffer allowed to scan global directories.
const char * GetItemField(TFolder *parent, TObject *item, const char *name)
return field for specified item
TRealData * GetRealData(const char *name) const
Return pointer to TRealData element with name "name".
void CreateNode(const char *_node_name)
Starts new node, must be closed at the end.
TObject * GetItem(const char *fullname, TFolder *&parent, Bool_t force=kFALSE, Bool_t within_objects=kTRUE)
return item from the subfolders structure
virtual const char * GetTitle() const
Returns title of object.
TList fRestrictions
! list of restrictions for different locations
TObject * FindTObjectInHierarchy(const char *path)
Search element in hierarchy, derived from TObject.
const char * Data() const