Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TRootSnifferFull.cxx
Go to the documentation of this file.
1// $Id$
2// Author: Sergey Linev 22/12/2013
3
4/*************************************************************************
5 * Copyright (C) 1995-2013, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12#include "TRootSnifferFull.h"
13
14#include "TH1.h"
15#include "TGraph.h"
16#include "TProfile.h"
17#include "TCanvas.h"
18#include "TFile.h"
19#include "TKey.h"
20#include "TList.h"
21#include "TMemFile.h"
22#include "TBufferFile.h"
23#include "TBufferJSON.h"
24#include "TBufferXML.h"
25#include "TROOT.h"
26#include "TFolder.h"
27#include "TTree.h"
28#include "TBranch.h"
29#include "TLeaf.h"
30#include "TClass.h"
31#include "TMethod.h"
32#include "TFunction.h"
33#include "TMethodArg.h"
34#include "TMethodCall.h"
35#include "TUrl.h"
36#include "TImage.h"
37#include "TVirtualMutex.h"
38#include "TRootSnifferStore.h"
39#include "THttpCallArg.h"
40
41#include <cstdlib>
42#include <cstring>
43
44/** \class TRootSnifferFull
45
46Extends TRootSniffer for many ROOT classes
47
48Provides access to different ROOT collections and containers
49like TTree, TCanvas, TFile, ...
50*/
51
52
53////////////////////////////////////////////////////////////////////////////////
54/// constructor
55
56TRootSnifferFull::TRootSnifferFull(const char *name, const char *objpath) : TRootSniffer(name, objpath)
57{
58}
59
60////////////////////////////////////////////////////////////////////////////////
61/// destructor
62
64{
65 delete fSinfo;
66
67 delete fMemFile;
68}
69
70////////////////////////////////////////////////////////////////////////////////
71/// return true if given class can be drawn in JSROOT
72
74{
75 if (!cl)
76 return kFALSE;
77 if (cl->InheritsFrom(TH1::Class()))
78 return kTRUE;
79 if (cl->InheritsFrom(TGraph::Class()))
80 return kTRUE;
82 return kTRUE;
84 return kTRUE;
85 return kFALSE;
86}
87
88////////////////////////////////////////////////////////////////////////////////
89/// Scans object properties
90///
91/// here such fields as `_autoload` or `_icon` properties depending on class or object name could be assigned
92/// By default properties, coded in the Class title are scanned. Example:
93///
94/// ClassDef(UserClassName, 1) // class comments *SNIFF* _field1=value _field2="string value"
95///
96/// Here *SNIFF* mark is important. After it all expressions like field=value are parsed
97/// One could use double quotes to code string values with spaces.
98/// Fields separated from each other with spaces
99
101{
102 if (obj && obj->InheritsFrom(TLeaf::Class())) {
103 rec.SetField("_more", "false", kFALSE);
104 rec.SetField("_can_draw", "false", kFALSE);
105 rec.SetField("_player", "drawLeafPlayer");
106 rec.SetField("_module", "draw_tree");
107 return;
108 }
109
111}
112
113////////////////////////////////////////////////////////////////////////////////
114/// Scans TKey properties
115///
116/// in special cases load objects from the file
117
119{
120 if (strcmp(key->GetClassName(), "TDirectoryFile") == 0) {
121 TRootSniffer::ScanKeyProperties(rec, key, obj, obj_class);
122 } else {
123 obj_class = TClass::GetClass(key->GetClassName());
124 if (obj_class && obj_class->InheritsFrom(TTree::Class())) {
125 if (rec.CanExpandItem()) {
126 // it is requested to expand tree element - read it
127 obj = key->ReadObj();
128 if (obj)
129 obj_class = obj->IsA();
130 } else {
131 rec.SetField("_ttree", "true", kFALSE); // indicate ROOT TTree
132 rec.SetField("_player", "drawTreePlayerKey");
133 rec.SetField("_module", "draw_tree");
134 // rec.SetField("_more", "true", kFALSE); // one could allow to extend
135 }
136 }
137 }
138}
139
140////////////////////////////////////////////////////////////////////////////////
141/// Scans object childs (if any)
142///
143/// here one scans collection, branches, trees and so on
144
146{
147 if (obj->InheritsFrom(TTree::Class())) {
148 if (!rec.IsReadOnly(fReadOnly)) {
149 rec.SetField("_ttree", "true", kFALSE); // indicate ROOT TTree
150 rec.SetField("_player", "drawTreePlayer");
151 rec.SetField("_module", "draw_tree");
152 }
153 ScanCollection(rec, ((TTree *)obj)->GetListOfLeaves());
154 } else if (obj->InheritsFrom(TBranch::Class())) {
155 ScanCollection(rec, ((TBranch *)obj)->GetListOfLeaves());
156 } else {
158 }
159}
160
161////////////////////////////////////////////////////////////////////////////////
162/// Returns hash value for streamer infos
163///
164/// At the moment - just number of items in streamer infos list.
165
167{
168 return fSinfo ? fSinfo->GetSize() : 0;
169}
170
171////////////////////////////////////////////////////////////////////////////////
172/// Return true if it is streamer info item name
173
175{
176 if (!itemname || (*itemname == 0))
177 return kFALSE;
178
179 return (strcmp(itemname, "StreamerInfo") == 0) || (strcmp(itemname, "StreamerInfo/") == 0);
180}
181
182////////////////////////////////////////////////////////////////////////////////
183/// Get hash function for specified item
184///
185/// Used to detect any changes in the specified object
186
188{
189 if (IsStreamerInfoItem(itemname))
190 return GetStreamerInfoHash();
191
192 return TRootSniffer::GetItemHash(itemname);
193}
194
195////////////////////////////////////////////////////////////////////////////////
196/// Creates TMemFile instance, which used for objects streaming
197///
198/// One could not use TBufferFile directly,
199/// while one also require streamer infos list
200
202{
203 if (fMemFile)
204 return;
205
206 TDirectory::TContext dirCtx{nullptr};
207 TFile::TContext fileCtx{nullptr};
208
209 fMemFile = new TMemFile("dummy.file", "RECREATE");
210 gROOT->GetListOfFiles()->Remove(fMemFile);
211
212 TH1F *d = new TH1F("d", "d", 10, 0, 10);
213 fMemFile->WriteObject(d, "h1");
214 delete d;
215
216 TGraph *gr = new TGraph(10);
217 gr->SetName("abc");
218 // // gr->SetDrawOptions("AC*");
219 fMemFile->WriteObject(gr, "gr1");
220 delete gr;
221
222 fMemFile->WriteStreamerInfo();
223
224 // make primary list of streamer infos
225 TList *l = new TList();
226
227 l->Add(gROOT->GetListOfStreamerInfo()->FindObject("TGraph"));
228 l->Add(gROOT->GetListOfStreamerInfo()->FindObject("TH1F"));
229 l->Add(gROOT->GetListOfStreamerInfo()->FindObject("TH1"));
230 l->Add(gROOT->GetListOfStreamerInfo()->FindObject("TNamed"));
231 l->Add(gROOT->GetListOfStreamerInfo()->FindObject("TObject"));
232
233 fMemFile->WriteObject(l, "ll");
234 delete l;
235
236 fMemFile->WriteStreamerInfo();
237
238 fSinfo = fMemFile->GetStreamerInfoList();
239}
240
241////////////////////////////////////////////////////////////////////////////////
242/// Search element with specified path
243///
244/// Returns pointer on element
245///
246/// Optionally one could obtain element class, member description
247/// and number of childs. When chld!=0, not only element is searched,
248/// but also number of childs are counted. When member!=0, any object
249/// will be scanned for its data members (disregard of extra options)
250
251void *TRootSnifferFull::FindInHierarchy(const char *path, TClass **cl, TDataMember **member, Int_t *chld)
252{
253 if (IsStreamerInfoItem(path)) {
254 // special handling for streamer info
256 if (cl && fSinfo)
257 *cl = fSinfo->IsA();
258 return fSinfo;
259 }
260
261 return TRootSniffer::FindInHierarchy(path, cl, member, chld);
262}
263
264////////////////////////////////////////////////////////////////////////////////
265/// Produce binary data for specified item
266///
267/// if "zipped" option specified in query, buffer will be compressed
268
269Bool_t TRootSnifferFull::ProduceBinary(const std::string &path, const std::string & /*query*/, std::string &res)
270{
271 if (path.empty())
272 return kFALSE;
273
274 const char *path_ = path.c_str();
275 if (*path_ == '/')
276 path_++;
277
278 TClass *obj_cl = nullptr;
279 void *obj_ptr = FindInHierarchy(path_, &obj_cl);
280 if (!obj_ptr || !obj_cl)
281 return kFALSE;
282
283 if (obj_cl->GetBaseClassOffset(TObject::Class()) != 0) {
284 Info("ProduceBinary", "Non-TObject class not supported");
285 return kFALSE;
286 }
287
288 // ensure that memfile exists
290
291 TDirectory::TContext dirCtx{nullptr};
292 TFile::TContext fileCtx{nullptr};
293
294 TObject *obj = (TObject *)obj_ptr;
295
296 TBufferFile *sbuf = new TBufferFile(TBuffer::kWrite, 100000);
297 sbuf->SetParent(fMemFile);
298 sbuf->MapObject(obj);
299 obj->Streamer(*sbuf);
300 if (fCurrentArg)
301 fCurrentArg->SetExtraHeader("RootClassName", obj_cl->GetName());
302
303 // produce actual version of streamer info
304 delete fSinfo;
305 fMemFile->WriteStreamerInfo();
306 fSinfo = fMemFile->GetStreamerInfoList();
307
308 res.resize(sbuf->Length());
309 std::copy((const char *)sbuf->Buffer(), (const char *)sbuf->Buffer() + sbuf->Length(), res.begin());
310
311 delete sbuf;
312
313 return kTRUE;
314}
315
316////////////////////////////////////////////////////////////////////////////////
317/// Produce ROOT file for specified item
318///
319/// File created in memory using TMemFile class.
320
321Bool_t TRootSnifferFull::ProduceRootFile(const std::string &path, const std::string & /*query*/, std::string &res)
322{
323 if (path.empty())
324 return kFALSE;
325
326 const char *path_ = path.c_str();
327 if (*path_ == '/')
328 path_++;
329
330 TClass *obj_cl = nullptr;
331 void *obj_ptr = FindInHierarchy(path_, &obj_cl);
332 if (!obj_ptr || !obj_cl)
333 return kFALSE;
334
335 const char *store_name = "object";
336
337 if (obj_cl->GetBaseClassOffset(TNamed::Class()) == 0) {
338 const char *obj_name = ((TNamed *) obj_ptr)->GetName();
339 if (obj_name && *obj_name)
340 store_name = obj_name;
341 }
342
343 TDirectory::TContext dirCtx{nullptr};
344 struct RestoreGFile {
345 TFile *oldFile{gFile};
346 ~RestoreGFile() { gFile = oldFile; }
347 } restoreGFile;
348
349 {
350 TMemFile memfile("dummy.file", "RECREATE",
351 TString::Format("Object %s", path.c_str()),
353 gROOT->GetListOfFiles()->Remove(&memfile);
354
355 memfile.WriteObjectAny(obj_ptr, obj_cl, store_name);
356 memfile.Close();
357
358 res.resize(memfile.GetSize());
359 memfile.CopyTo(res.data(), memfile.GetSize());
360 }
361
362 return kTRUE;
363}
364
365
366////////////////////////////////////////////////////////////////////////////////
367/// Method to produce image from specified object
368///
369/// @param kind image kind TImage::kPng, TImage::kJpeg, TImage::kGif
370/// @param path path to object
371/// @param options extra options
372/// @param res std::string with binary data
373///
374/// By default, image 300x200 is produced
375/// In options string one could provide following parameters:
376///
377/// * w - image width
378/// * h - image height
379/// * opt - draw options
380///
381/// For instance:
382///
383/// http://localhost:8080/Files/hsimple.root/hpx/get.png?w=500&h=500&opt=lego1
384
385Bool_t TRootSnifferFull::ProduceImage(Int_t kind, const std::string &path, const std::string &options, std::string &res)
386{
387 if (path.empty())
388 return kFALSE;
389
390 const char *path_ = path.c_str();
391 if (*path_ == '/')
392 path_++;
393
394 TClass *obj_cl(nullptr);
395 void *obj_ptr = FindInHierarchy(path_, &obj_cl);
396 if (!obj_ptr || !obj_cl)
397 return kFALSE;
398
399 if (obj_cl->GetBaseClassOffset(TObject::Class()) != 0) {
400 Error("TRootSniffer", "Only derived from TObject classes can be drawn");
401 return kFALSE;
402 }
403
404 TObject *obj = (TObject *)obj_ptr;
405
406 TImage *img = TImage::Create();
407 if (!img)
408 return kFALSE;
409
410 if (obj->InheritsFrom(TPad::Class())) {
411
412 if (gDebug > 1)
413 Info("TRootSniffer", "Crate IMAGE directly from pad");
414 img->FromPad((TPad *)obj);
415 } else if (CanDrawClass(obj->IsA())) {
416
417 if (gDebug > 1)
418 Info("TRootSniffer", "Crate IMAGE from object %s", obj->GetName());
419
420 Int_t width = 300, height = 200;
421 TString drawopt;
422
423 if (!options.empty()) {
424 TUrl url;
425 url.SetOptions(options.c_str());
426 url.ParseOptions();
427 Int_t w = url.GetIntValueFromOptions("w");
428 if (w > 10)
429 width = w;
430 Int_t h = url.GetIntValueFromOptions("h");
431 if (h > 10)
432 height = h;
433 drawopt = DecodeUrlOptionValue(url.GetValueFromOptions("opt"), kTRUE);
434 }
435
436 Bool_t isbatch = gROOT->IsBatch();
437 TVirtualPad::TContext ctxt(false);
438
439 if (!isbatch)
440 gROOT->SetBatch(kTRUE);
441
442 TCanvas *c1 = new TCanvas("__online_draw_canvas__", "title", width, height);
443 obj->Draw(drawopt.Data());
444 img->FromPad(c1);
445 delete c1;
446
447 if (!isbatch)
448 gROOT->SetBatch(kFALSE);
449
450 } else {
451 delete img;
452 return kFALSE;
453 }
454
455 TImage *im = TImage::Create();
456 im->Append(img);
457
458 char *png_buffer = nullptr;
459 int size(0);
460
461 im->GetImageBuffer(&png_buffer, &size, (TImage::EImageFileTypes)kind);
462
463 if (png_buffer && (size > 0)) {
464 res.resize(size);
465 memcpy((void *)res.data(), png_buffer, size);
466 }
467
468 free(png_buffer);
469 delete im;
470
471 return !res.empty();
472}
473
474////////////////////////////////////////////////////////////////////////////////
475/// Invokes TRootSniffer::ProduceIamge, converting kind into TImage::EImageFileTypes type
476
477Bool_t TRootSnifferFull::CallProduceImage(const std::string &kind, const std::string &path, const std::string &options, std::string &res)
478{
479 if (kind == "png")
480 return ProduceImage(TImage::kPng, path, options, res);
481
482 if (kind == "jpeg")
483 return ProduceImage(TImage::kJpeg, path, options, res);
484
485 if (kind == "gif")
486 return ProduceImage(TImage::kGif, path, options, res);
487
488 return kFALSE;
489}
490
491////////////////////////////////////////////////////////////////////////////////
492/// Produce XML data for specified item
493///
494/// For object conversion TBufferXML is used
495
496Bool_t TRootSnifferFull::ProduceXml(const std::string &path, const std::string & /*options*/, std::string &res)
497{
498 if (path.empty())
499 return kFALSE;
500 const char *path_ = path.c_str();
501 if (*path_ == '/')
502 path_++;
503
504 TClass *obj_cl = nullptr;
505 void *obj_ptr = FindInHierarchy(path_, &obj_cl);
506 if (!obj_ptr || !obj_cl)
507 return kFALSE;
508
509 // TODO: support std::string in TBufferXML
510 res = TBufferXML::ConvertToXML(obj_ptr, obj_cl).Data();
511
512 return !res.empty();
513}
514
515class TArgHolderBase : public TObject {
516 public:
518 virtual const void *GetPtr() const { return nullptr; }
519};
520
521template<typename T>
523 public:
526 const void *GetPtr() const override { return &fValue; }
527};
528
530 public:
532 const char *fBuf = nullptr;
533 TArgHolderConstChar(const char *v) : fValue(v) { fBuf = fValue.Data(); }
534 const void *GetPtr() const override { return &fBuf; }
535};
536
537
538////////////////////////////////////////////////////////////////////////////////
539/// Execute command for specified object
540///
541/// @param path the object path
542/// @param options include method and extra list of parameters
543/// sniffer should be not-readonly to allow execution of the commands
544/// @param reskind defines kind of result 0 - debug, 1 - json, 2 - binary
545/// @param res_str result string
546
547Bool_t TRootSnifferFull::ProduceExe(const std::string &path, const std::string &options, Int_t reskind, std::string &res_str)
548{
549 std::string *debug = (reskind == 0) ? &res_str : nullptr;
550
551 if (path.empty()) {
552 if (debug)
553 debug->append("Item name not specified\n");
554 return debug != nullptr;
555 }
556
557 const char *path_ = path.c_str();
558 if (*path_ == '/')
559 path_++;
560
561 TClass *obj_cl = nullptr;
562 void *obj_ptr = FindInHierarchy(path_, &obj_cl);
563 if (debug)
564 debug->append(TString::Format("Item:%s found:%s\n", path_, obj_ptr ? "true" : "false").Data());
565 if (!obj_ptr || !obj_cl)
566 return debug != nullptr;
567
568 TUrl url;
569 url.SetOptions(options.c_str());
570
571 const char *method_name = url.GetValueFromOptions("method");
572 TString prototype = DecodeUrlOptionValue(url.GetValueFromOptions("prototype"), kTRUE);
573 TString funcname = DecodeUrlOptionValue(url.GetValueFromOptions("func"), kTRUE);
574 TMethod *method = nullptr;
575 TFunction *func = nullptr;
576 if (method_name) {
577 if (prototype.Length() == 0) {
578 if (debug)
579 debug->append(TString::Format("Search for any method with name \'%s\'\n", method_name).Data());
580 method = obj_cl->GetMethodAllAny(method_name);
581 } else {
582 if (debug)
583 debug->append(
584 TString::Format("Search for method \'%s\' with prototype \'%s\'\n", method_name, prototype.Data())
585 .Data());
586 method = obj_cl->GetMethodWithPrototype(method_name, prototype);
587 }
588 }
589
590 if (method) {
591 if (debug)
592 debug->append(TString::Format("Method: %s\n", method->GetPrototype()).Data());
593 } else {
594 if (funcname.Length() > 0) {
595 if (prototype.Length() == 0) {
596 if (debug)
597 debug->append(TString::Format("Search for any function with name \'%s\'\n", funcname.Data()).Data());
598 func = gROOT->GetGlobalFunction(funcname);
599 } else {
600 if (debug)
601 debug->append(TString::Format("Search for function \'%s\' with prototype \'%s\'\n", funcname.Data(),
602 prototype.Data())
603 .Data());
604 func = gROOT->GetGlobalFunctionWithPrototype(funcname, prototype);
605 }
606 }
607
608 if (func && debug)
609 debug->append(TString::Format("Function: %s\n", func->GetPrototype()).Data());
610 }
611
612 if (!method && !func) {
613 if (debug)
614 debug->append("Method not found\n");
615 return debug != nullptr;
616 }
617
618 if ((fReadOnly && (fCurrentRestrict == 0)) || (fCurrentRestrict == 1)) {
619 if ((method != nullptr) && (fCurrentAllowedMethods.Index(method_name) == kNPOS)) {
620 if (debug)
621 debug->append("Server runs in read-only mode, method cannot be executed\n");
622 return debug != nullptr;
623 } else if ((func != nullptr) && (fCurrentAllowedMethods.Index(funcname) == kNPOS)) {
624 if (debug)
625 debug->append("Server runs in read-only mode, function cannot be executed\n");
626 return debug != nullptr;
627 } else {
628 if (debug)
629 debug->append("For that special method server allows access even read-only mode is specified\n");
630 }
631 }
632
633 TList *args = method ? method->GetListOfMethodArgs() : func->GetListOfMethodArgs();
634
635 TList garbage;
636 garbage.SetOwner(kTRUE); // use as garbage collection
637 TObject *post_obj = nullptr; // object reconstructed from post request
638 TString call_args;
639 std::vector<const void *> plain_args;
640 Bool_t can_use_plain = kTRUE, add_plain = kFALSE;
641
642 auto add_plain_arg = [&plain_args, &garbage, &add_plain](TArgHolderBase *arg) {
643 plain_args.emplace_back(arg->GetPtr());
644 garbage.Add(arg);
645 add_plain = kTRUE;
646 };
647
648 TIter next(args);
649 while (auto arg = static_cast<TMethodArg *>(next())) {
650 add_plain = kFALSE;
651
652 if ((strcmp(arg->GetName(), "rest_url_opt") == 0) && (strcmp(arg->GetFullTypeName(), "const char*") == 0) &&
653 (args->GetSize() == 1)) {
654 // very special case - function requires list of options after method=argument
655
656 const char *pos = strstr(options.c_str(), "method=");
657 if (!pos || (strlen(pos) < strlen(method_name) + 7))
658 return debug != nullptr;
659 const char *rest_url = pos + strlen(method_name) + 7;
660 if (*rest_url == '&') ++rest_url;
661 call_args.Append("\"");
662 call_args.Append(DecodeUrlOptionValue(rest_url, kTRUE));
663 call_args.Append("\"");
664 add_plain_arg(new TArgHolderConstChar(rest_url));
665 break;
666 }
667
668 TString sval;
669 const char *val = url.GetValueFromOptions(arg->GetName());
670 if (val)
671 sval = DecodeUrlOptionValue(val, kTRUE);
672
673 Bool_t sanitize_numeric = kFALSE;
674
675 if (sval == "_this_") {
676 // special case - object itself is used as argument
677 sval.Form("(%s*)0x%zx", obj_cl->GetName(), (size_t)obj_ptr);
678 add_plain_arg(new TArgHolder<void*>(obj_ptr));
679 } else if ((fCurrentArg != nullptr) && (fCurrentArg->GetPostData() != nullptr)) {
680 // process several arguments which are specific for post requests
681 if (fAllowPostObject && (sval == "_post_object_xml_")) {
682 // post data has extra 0 at the end and can be used as null-terminated string
683 post_obj = TBufferXML::ConvertFromXML((const char *)fCurrentArg->GetPostData());
684 if (!post_obj)
685 sval = "0";
686 else {
687 sval.Form("(%s*)0x%zx", post_obj->ClassName(), (size_t)post_obj);
688 if (url.HasOption("_destroy_post_"))
689 garbage.Add(post_obj);
690 }
691 add_plain_arg(new TArgHolder<void*>(post_obj));
692 } else if (fAllowPostObject && (sval == "_post_object_json_")) {
693 // post data has extra 0 at the end and can be used as null-terminated string
694 post_obj = TBufferJSON::ConvertFromJSON((const char *)fCurrentArg->GetPostData());
695 if (!post_obj)
696 sval = "0";
697 else {
698 sval.Form("(%s*)0x%zx", post_obj->ClassName(), (size_t)post_obj);
699 if (url.HasOption("_destroy_post_"))
700 garbage.Add(post_obj);
701 }
702 add_plain_arg(new TArgHolder<void*>(post_obj));
703 } else if (fAllowPostObject && (sval == "_post_object_") && url.HasOption("_post_class_")) {
704 TString clname = DecodeUrlOptionValue(url.GetValueFromOptions("_post_class_"), kTRUE);
705 TClass *arg_cl = gROOT->GetClass(clname, kTRUE, kTRUE);
706 if ((arg_cl != nullptr) && (arg_cl->GetBaseClassOffset(TObject::Class()) == 0) && (post_obj == nullptr)) {
707 post_obj = (TObject *)arg_cl->New();
708 if (post_obj == nullptr) {
709 if (debug)
710 debug->append(TString::Format("Fail to create object of class %s\n", clname.Data()).Data());
711 } else {
712 if (debug)
713 debug->append(TString::Format("Reconstruct object of class %s from POST data\n", clname.Data()).Data());
714 TBufferFile buf(TBuffer::kRead, fCurrentArg->GetPostDataLength(), (void *)fCurrentArg->GetPostData(), kFALSE);
715 buf.MapObject(post_obj, arg_cl);
716 post_obj->Streamer(buf);
717 if (url.HasOption("_destroy_post_"))
718 garbage.Add(post_obj);
719 }
720 }
721 if (!post_obj)
722 sval = "0";
723 else
724 sval.Form("(%s*)0x%zx", clname.Data(), (size_t)post_obj);
725 add_plain_arg(new TArgHolder<void*>(post_obj));
726 } else if (sval == "_post_data_") {
727 sval.Form("(void*)0x%zx", (size_t)fCurrentArg->GetPostData());
728 add_plain_arg(new TArgHolder<const void*>(fCurrentArg->GetPostData()));
729 } else if (sval == "_post_length_")
730 sval.Form("%ld", (long)fCurrentArg->GetPostDataLength());
731 else
732 sanitize_numeric = kTRUE;
733 } else
734 sanitize_numeric = kTRUE;
735
736 if (sval.IsNull() && arg->GetDefault())
737 sval = arg->GetDefault();
738
739 if (debug)
740 debug->append(
741 TString::Format(" Argument:%s Type:%s Value:%s \n", arg->GetName(), arg->GetFullTypeName(), sval.Data())
742 .Data());
743
744 if (call_args.Length() > 0)
745 call_args += ", ";
746
747 if (!add_plain) {
748 std::string tname = arg->GetTypeNormalizedName();
749 if (tname == "const char*")
750 // one can use original string, just remove optional quotes
751 add_plain_arg(new TArgHolderConstChar(DecodeUrlOptionValue(val, kTRUE, kFALSE)));
752 else if (tname == "bool")
753 add_plain_arg(new TArgHolder<bool>(!sval.IsNull() && (sval != "0") && (sval != "false")));
754 else if (tname == "double")
755 add_plain_arg(new TArgHolder<double>(std::stod(sval.Data())));
756 else if (tname == "float")
757 add_plain_arg(new TArgHolder<float>(std::stof(sval.Data())));
758 else if (tname == "int")
759 add_plain_arg(new TArgHolder<int>(std::stol(sval.Data())));
760 else if (tname == "long")
761 add_plain_arg(new TArgHolder<long>(std::stol(sval.Data())));
762 else if (tname == "short")
763 add_plain_arg(new TArgHolder<short>(std::stol(sval.Data())));
764 else if (tname == "char")
765 add_plain_arg(new TArgHolder<char>(std::stol(sval.Data())));
766 else if (tname == "unsigned int")
767 add_plain_arg(new TArgHolder<unsigned int>(std::stoul(sval.Data())));
768 else if (tname == "unisgned long")
769 add_plain_arg(new TArgHolder<unsigned long>(std::stoul(sval.Data())));
770 else if (tname == "unsigned short")
771 add_plain_arg(new TArgHolder<unsigned short>(std::stoul(sval.Data())));
772 else if (tname == "unsigned char")
773 add_plain_arg(new TArgHolder<unsigned char>(std::stoul(sval.Data())));
774 else if (!tname.empty() && tname.back() == '*' && (sval == "0" || sval == "null" || sval == "nullptr"))
775 add_plain_arg(new TArgHolder<Longptr_t>(0));
776 else
777 can_use_plain = kFALSE; // unsupported type, plain args cannot be used
778 }
779
780 Bool_t isstr = (strcmp(arg->GetFullTypeName(), "const char*") == 0) ||
781 (strcmp(arg->GetFullTypeName(), "Option_t*") == 0) ||
782 (strcmp(arg->GetFullTypeName(), "string") == 0);
783
784 if (isstr) {
785 // check that quotes provided for the string argument
786 // all special characters were escaped before
787 if (sval.IsNull())
788 sval = "\"\"";
789 else {
790 if (sval[0] != '"')
791 sval.Prepend("\"");
792 if (sval[sval.Length() - 1] != '"')
793 sval.Append("\"");
794 }
795 } else {
796 // for numeric types keep only numeric and alphabetic characters
797 // exclude others - especially remove all escape characters
798 if (sanitize_numeric) {
799 TString sanitized;
800 for(Size_t i = 0; i < sval.Length(); ++i) {
801 if (std::isalnum(sval[i]) || std::strchr(".:+-", sval[i]))
802 sanitized.Append(sval[i]);
803 }
804 sval = sanitized;
805 }
806 if (sval.IsNull())
807 sval = "0";
808 }
809
810 call_args.Append(sval);
811 }
812
813 TMethodCall *call = nullptr;
814
815 if (method != nullptr) {
816 if (can_use_plain) {
817 // prevent creation of huge cache
818 if (fExeCache.size() > 1000)
819 fExeCache.clear();
820 auto iter = fExeCache.find(method);
821 if (iter != fExeCache.end()) {
822 call = iter->second.get();
823 } else {
824 call = new TMethodCall();
825 call->InitWithPrototype(obj_cl, method_name, prototype.IsNull() ? nullptr : prototype.Data());
826 fExeCache.emplace(method, std::unique_ptr<TMethodCall>(call));
827 }
828 } else {
829 call = new TMethodCall(obj_cl, method_name, call_args.Data());
830 garbage.Add(call);
831 }
832 if (debug)
833 debug->append(TString::Format("Calling obj->%s(%s);\n", method_name, call_args.Data()).Data());
834 } else {
835 call = new TMethodCall(funcname.Data(), call_args.Data());
836 garbage.Add(call);
837 if (debug)
838 debug->append(TString::Format("Calling %s(%s);\n", funcname.Data(), call_args.Data()).Data());
839 }
840
841 if (!call->IsValid()) {
842 if (debug)
843 debug->append("Fail: invalid TMethodCall\n");
844 return debug != nullptr;
845 }
846
847 Int_t compact = 0;
848 if (url.GetValueFromOptions("compact"))
849 compact = url.GetIntValueFromOptions("compact");
850
851 TString res = "null";
852 void *ret_obj = nullptr;
853 TClass *ret_cl = nullptr;
854 TBufferFile *resbuf = nullptr;
855 if (reskind == 2) {
856 resbuf = new TBufferFile(TBuffer::kWrite, 10000);
857 garbage.Add(resbuf);
858 }
859
860 auto ret_type = call->ReturnType();
861 if (ret_type == TMethodCall::kOther) {
862 std::string ret_kind = func ? func->GetReturnTypeNormalizedName() : method->GetReturnTypeNormalizedName();
863 if ((ret_kind.length() > 0) && (ret_kind[ret_kind.length() - 1] == '*')) {
864 ret_kind.resize(ret_kind.length() - 1);
865 ret_cl = gROOT->GetClass(ret_kind.c_str(), kTRUE, kTRUE);
866 }
867 if (!ret_cl)
868 ret_type = TMethodCall::kNone;
869 }
870
871 switch (ret_type) {
872 case TMethodCall::kLong: {
873 Longptr_t l = 0;
874 if (method && can_use_plain)
875 call->Execute(obj_ptr, plain_args.data(), plain_args.size(), &l);
876 else if (method)
877 call->Execute(obj_ptr, l);
878 else
879 call->Execute(l);
880 if (resbuf)
881 resbuf->WriteLong(l);
882 else
883 res.Form("%zd", (size_t)l);
884 break;
885 }
887 Double_t d = 0.;
888 if (method && can_use_plain)
889 call->Execute(obj_ptr, plain_args.data(), plain_args.size(), &d);
890 else if (method)
891 call->Execute(obj_ptr, d);
892 else
893 call->Execute(d);
894 if (resbuf)
895 resbuf->WriteDouble(d);
896 else
898 break;
899 }
901 char *txt = nullptr;
902 if (method && can_use_plain)
903 call->Execute(obj_ptr, plain_args.data(), plain_args.size(), &txt);
904 else if (method)
905 call->Execute(obj_ptr, &txt);
906 else
907 call->Execute(&txt);
908 if (txt != nullptr) {
909 if (resbuf)
910 resbuf->WriteString(txt);
911 else
912 res.Form("\"%s\"", txt);
913 }
914 break;
915 }
916 case TMethodCall::kOther: {
917 Longptr_t l = 0;
918 if (method && can_use_plain)
919 call->Execute(obj_ptr, plain_args.data(), plain_args.size(), &l);
920 else if (method)
921 call->Execute(obj_ptr, l);
922 else
923 call->Execute(l);
924 if (l != 0)
925 ret_obj = (void *)l;
926 break;
927 }
928 case TMethodCall::kNone: {
929 if (method && can_use_plain)
930 call->Execute(obj_ptr, plain_args.data(), plain_args.size());
931 else if (method)
932 call->Execute(obj_ptr);
933 else
934 call->Execute();
935 break;
936 }
937 }
938
939 const char *_ret_object_ = url.GetValueFromOptions("_ret_object_");
940 if (_ret_object_ != nullptr) {
941 TObject *obj = nullptr;
942 if (gDirectory)
943 obj = gDirectory->Get(_ret_object_);
944 if (debug)
945 debug->append(TString::Format("Return object %s found %s\n", _ret_object_, obj ? "true" : "false").Data());
946
947 if (obj == nullptr) {
948 res = "null";
949 } else {
950 ret_obj = obj;
951 ret_cl = obj->IsA();
952 }
953 }
954
955 if (ret_obj && ret_cl) {
956 if ((resbuf != nullptr) && (ret_cl->GetBaseClassOffset(TObject::Class()) == 0)) {
957 TObject *obj = (TObject *)ret_obj;
958 resbuf->MapObject(obj);
959 obj->Streamer(*resbuf);
960 if (fCurrentArg)
961 fCurrentArg->SetExtraHeader("RootClassName", ret_cl->GetName());
962 } else {
963 res = TBufferJSON::ConvertToJSON(ret_obj, ret_cl, compact);
964 }
965 }
966
967 if ((resbuf != nullptr) && (resbuf->Length() > 0)) {
968 res_str.resize(resbuf->Length());
969 std::copy((const char *)resbuf->Buffer(), (const char *)resbuf->Buffer() + resbuf->Length(), res_str.begin());
970 }
971
972 if (debug)
973 debug->append(TString::Format("Result = %s\n", res.Data()).Data());
974
975 if (reskind == 1)
976 res_str = res.Data();
977
978 if (url.HasOption("_destroy_result_") && ret_obj && ret_cl) {
979 ret_cl->Destructor(ret_obj);
980 if (debug)
981 debug->append("Destroy result object at the end\n");
982 }
983
984 // delete all garbage objects, but should be also done with any return
985 garbage.Delete();
986
987 return kTRUE;
988}
#define d(i)
Definition RSha256.hxx:102
#define h(i)
Definition RSha256.hxx:106
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
bool Bool_t
Boolean (0=false, 1=true) (bool)
Definition RtypesCore.h:77
int Int_t
Signed integer 4 bytes (int)
Definition RtypesCore.h:59
float Size_t
Attribute size (float)
Definition RtypesCore.h:103
long Longptr_t
Integer large enough to hold a pointer (platform-dependent)
Definition RtypesCore.h:89
unsigned long ULong_t
Unsigned long integer 4 bytes (unsigned long). Size depends on architecture.
Definition RtypesCore.h:69
constexpr Bool_t kFALSE
Definition RtypesCore.h:108
double Double_t
Double 8 bytes.
Definition RtypesCore.h:73
constexpr Ssiz_t kNPOS
The equivalent of std::string::npos for the ROOT class TString.
Definition RtypesCore.h:131
constexpr Bool_t kTRUE
Definition RtypesCore.h:107
#define gDirectory
Definition TDirectory.h:385
#define gFile
Definition TFile.h:439
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void w
Option_t Option_t width
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t height
char name[80]
Definition TGX11.cxx:148
Int_t gDebug
Definition TROOT.cxx:777
#define gROOT
Definition TROOT.h:417
#define free
Definition civetweb.c:1578
virtual const void * GetPtr() const
TArgHolderConstChar(const char *v)
const void * GetPtr() const override
const void * GetPtr() const override
A TTree is a list of TBranches.
Definition TBranch.h:93
static TClass * Class()
The concrete implementation of TBuffer for writing/reading to/from a ROOT file or socket.
Definition TBufferFile.h:47
void WriteLong(Long_t l) override
void WriteString(const char *s) override
Write string to I/O buffer.
void WriteDouble(Double_t d) override
void MapObject(const TObject *obj, UInt_t offset=1) override
Add object to the fMap container.
static TObject * ConvertFromJSON(const char *str)
Read TObject-based class from JSON, produced by ConvertToJSON() method.
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...
static const char * GetFloatFormat()
return current printf format for float members, default "%e"
static TString ConvertToXML(const TObject *obj, Bool_t GenericLayout=kFALSE, Bool_t UseNamespaces=kFALSE)
Converts object, inherited from TObject class, to XML string GenericLayout defines layout choice for ...
static TObject * ConvertFromXML(const char *str, Bool_t GenericLayout=kFALSE, Bool_t UseNamespaces=kFALSE)
Read object from XML, produced by ConvertToXML() method.
void SetParent(TObject *parent)
Set parent owning this buffer.
Definition TBuffer.cxx:269
@ kWrite
Definition TBuffer.h:73
@ kRead
Definition TBuffer.h:73
Int_t Length() const
Definition TBuffer.h:100
char * Buffer() const
Definition TBuffer.h:96
The Canvas class.
Definition TCanvas.h:23
static TClass * Class()
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition TClass.h:84
void * New(ENewType defConstructor=kClassNew, Bool_t quiet=kFALSE) const
Return a pointer to a newly allocated object of this class.
Definition TClass.cxx:5048
TMethod * GetMethodWithPrototype(const char *method, const char *proto, Bool_t objectIsConst=kFALSE, ROOT::EFunctionMatchMode mode=ROOT::kConversionMatch)
Find the method with a given prototype.
Definition TClass.cxx:4514
void Destructor(void *obj, Bool_t dtorOnly=kFALSE)
Explicitly call destructor for object.
Definition TClass.cxx:5470
Bool_t InheritsFrom(const char *cl) const override
Return kTRUE if this class inherits from a class with name "classname".
Definition TClass.cxx:4932
Int_t GetBaseClassOffset(const TClass *toBase, void *address=nullptr, bool isDerivedObject=true)
Definition TClass.cxx:2812
TMethod * GetMethodAllAny(const char *method)
Return pointer to method without looking at parameters.
Definition TClass.cxx:4442
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:2994
virtual void SetOwner(Bool_t enable=kTRUE)
Set whether this collection is the owner (enable==true) of its content.
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
All ROOT classes may have RTTI (run time type identification) support added.
Definition TDataMember.h:31
Int_t WriteObjectAny(const void *obj, const char *classname, const char *name, Option_t *option="", Int_t bufsize=0) override
Write object from pointer of class classname in this directory.
TDirectory::TContext keeps track and restore the current directory.
Definition TDirectory.h:89
A file, usually with extension .root, that stores data and code in the form of serialized objects in ...
Definition TFile.h:130
void Close(Option_t *option="") override
Close a file.
Definition TFile.cxx:989
Global functions class (global functions are obtained from CINT).
Definition TFunction.h:30
virtual const char * GetPrototype() const
Returns the prototype of a function as defined by CINT, or 0 in case of error.
TList * GetListOfMethodArgs()
Return list containing the TMethodArgs of a TFunction.
std::string GetReturnTypeNormalizedName() const
Get the normalized name of the return type.
A TGraph is an object made of two arrays X and Y with npoints each.
Definition TGraph.h:41
static TClass * Class()
1-D histogram with a float per channel (see TH1 documentation)
Definition TH1.h:878
static TClass * Class()
An abstract interface to image processing library.
Definition TImage.h:29
virtual void FromPad(TVirtualPad *, Int_t=0, Int_t=0, UInt_t=0, UInt_t=0)
Definition TImage.h:122
EImageFileTypes
Definition TImage.h:36
@ kPng
Definition TImage.h:40
@ kJpeg
Definition TImage.h:41
@ kGif
Definition TImage.h:48
static TImage * Create()
Create an image.
Definition TImage.cxx:34
virtual void Append(const TImage *, const char *="+", const char *="#00000000")
Definition TImage.h:175
virtual void GetImageBuffer(char **, int *, EImageFileTypes=TImage::kPng)
Definition TImage.h:242
Book space in a file, create I/O buffers, to fill them, (un)compress them.
Definition TKey.h:28
virtual const char * GetClassName() const
Definition TKey.h:77
virtual TObject * ReadObj()
To read a TObject* from the file.
Definition TKey.cxx:804
static TClass * Class()
A doubly linked list.
Definition TList.h:38
void Add(TObject *obj) override
Definition TList.h:81
void Delete(Option_t *option="") override
Remove all objects from the list AND delete all heap based objects.
Definition TList.cxx:600
A TMemFile is like a normal TFile except that it reads and writes only from memory.
Definition TMemFile.h:27
Long64_t GetSize() const override
Return the current size of the memory file.
Definition TMemFile.cxx:289
virtual Long64_t CopyTo(void *to, Long64_t maxsize) const
Copy the binary representation of the TMemFile into the memory area starting at 'to' and of length at...
Definition TMemFile.cxx:254
Each ROOT method (see TMethod) has a linked list of its arguments.
Definition TMethodArg.h:36
Method or function calling interface.
Definition TMethodCall.h:37
EReturnType ReturnType()
Returns the return type of the method.
static const EReturnType kLong
Definition TMethodCall.h:43
static const EReturnType kString
Definition TMethodCall.h:45
static const EReturnType kOther
Definition TMethodCall.h:46
static const EReturnType kNone
Definition TMethodCall.h:49
void Execute(const char *, const char *, int *=nullptr) override
Execute method on this object with the given parameter string, e.g.
Definition TMethodCall.h:64
Bool_t IsValid() const
Return true if the method call has been properly initialized and is usable.
void InitWithPrototype(TClass *cl, const char *method, const char *proto, Bool_t objectIsConst=kFALSE, ROOT::EFunctionMatchMode mode=ROOT::kConversionMatch)
Initialize the method invocation environment.
static const EReturnType kDouble
Definition TMethodCall.h:44
Each ROOT class (see TClass) has a linked list of methods.
Definition TMethod.h:38
virtual TList * GetListOfMethodArgs()
Returns methodarg list and additionally updates fDataMember in TMethod by calling FindDataMember();.
Definition TMethod.cxx:306
const char * GetName() const override
Returns name of object.
Definition TNamed.h:49
TNamed()
Definition TNamed.h:38
static TClass * Class()
virtual const char * GetName() const
Returns name of object.
Definition TObject.cxx:462
virtual void Streamer(TBuffer &)
Stream an object of class TObject.
Definition TObject.cxx:997
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition TObject.cxx:227
static TClass * Class()
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition TObject.cxx:549
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:1098
virtual TClass * IsA() const
Definition TObject.h:248
virtual void Draw(Option_t *option="")
Default Draw method for all objects.
Definition TObject.cxx:293
TObject()
TObject constructor.
Definition TObject.h:259
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition TObject.cxx:1072
The most important graphics class in the ROOT system.
Definition TPad.h:28
static TClass * Class()
static TClass * Class()
void * FindInHierarchy(const char *path, TClass **cl=nullptr, TDataMember **member=nullptr, Int_t *chld=nullptr) override
Search element with specified path.
Bool_t IsStreamerInfoItem(const char *itemname) override
Return true if it is streamer info item name.
static Bool_t IsDrawableClass(TClass *cl)
return true if given class can be drawn in JSROOT
Bool_t ProduceExe(const std::string &path, const std::string &options, Int_t reskind, std::string &res) override
Execute command for specified object.
TList * fSinfo
! last produced streamer info
TRootSnifferFull(const char *name="sniff", const char *objpath="Objects")
constructor
Bool_t CanDrawClass(TClass *cl) override
void ScanObjectProperties(TRootSnifferScanRec &rec, TObject *obj) override
Scans object properties.
virtual ~TRootSnifferFull()
destructor
void ScanObjectChilds(TRootSnifferScanRec &rec, TObject *obj) override
Scans object childs (if any)
std::map< const TMethod *, std::unique_ptr< TMethodCall > > fExeCache
! cache for exe.json invocation
Bool_t ProduceRootFile(const std::string &path, const std::string &options, std::string &res) override
Produce ROOT file for specified item.
ULong_t GetItemHash(const char *itemname) override
Get hash function for specified item.
Bool_t ProduceImage(Int_t kind, const std::string &path, const std::string &options, std::string &res) override
Method to produce image from specified object.
Bool_t CallProduceImage(const std::string &kind, const std::string &path, const std::string &options, std::string &res) override
Invokes TRootSniffer::ProduceIamge, converting kind into TImage::EImageFileTypes type.
Bool_t ProduceXml(const std::string &path, const std::string &options, std::string &res) override
Produce XML data for specified item.
void CreateMemFile()
Creates TMemFile instance, which used for objects streaming.
Bool_t ProduceBinary(const std::string &path, const std::string &options, std::string &res) override
Produce binary data for specified item.
TMemFile * fMemFile
! file used to manage streamer infos
ULong_t GetStreamerInfoHash() override
Returns hash value for streamer infos.
void ScanKeyProperties(TRootSnifferScanRec &rec, TKey *key, TObject *&obj, TClass *&obj_class) override
Scans TKey properties.
Structure used to scan hierarchies of ROOT objects.
Bool_t CanExpandItem()
Returns true when item can be expanded.
void SetField(const char *name, const char *value, Bool_t with_quotes=kTRUE)
Set item field only when creating is specified.
Bool_t IsReadOnly(Bool_t dflt=kTRUE)
Returns read-only flag for current item.
TRootSniffer(const char *name="sniff", const char *objpath="Objects")
constructor
virtual void ScanObjectChilds(TRootSnifferScanRec &rec, TObject *obj)
scans object childs (if any) here one scans collection, branches, trees and so on
TString DecodeUrlOptionValue(const char *value, Bool_t remove_quotes=kTRUE, Bool_t escape_special=kTRUE)
Method replaces all kind of special symbols, which could appear in URL options.
TString fCurrentAllowedMethods
! list of allowed methods, extracted when analyzed object restrictions
virtual void ScanKeyProperties(TRootSnifferScanRec &rec, TKey *key, TObject *&obj, TClass *&obj_class)
Scans TKey properties in special cases load objects from the file.
Bool_t fAllowPostObject
! when true allow to deserialize objects received via POST requests
virtual void ScanObjectProperties(TRootSnifferScanRec &rec, TObject *obj)
Scans object properties here such fields as _autoload or _icon properties depending on class or objec...
virtual ULong_t GetItemHash(const char *itemname)
Get hash function for specified item used to detect any changes in the specified object.
Bool_t fReadOnly
! indicate if sniffer allowed to change ROOT structures - like read objects from file
THttpCallArg * fCurrentArg
! current http arguments (if any)
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...
Int_t fCurrentRestrict
! current restriction for last-found object
void ScanCollection(TRootSnifferScanRec &rec, TCollection *lst, const char *foldername=nullptr, TCollection *keys_lst=nullptr)
Scan collection content.
Basic string class.
Definition TString.h:138
Ssiz_t Length() const
Definition TString.h:427
const char * Data() const
Definition TString.h:386
TString & Prepend(const char *cs)
Definition TString.h:684
Bool_t IsNull() const
Definition TString.h:424
TString & Append(const char *cs)
Definition TString.h:583
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString.
Definition TString.cxx:2459
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition TString.cxx:2437
A TTree represents a columnar dataset.
Definition TTree.h:89
static TClass * Class()
This class represents a WWW compatible URL.
Definition TUrl.h:33
const char * GetValueFromOptions(const char *key) const
Return a value for a given key from the URL options.
Definition TUrl.cxx:662
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.
Definition TUrl.cxx:674
void SetOptions(const char *opt)
Definition TUrl.h:87
void ParseOptions() const
Parse URL options into a key/value map.
Definition TUrl.cxx:628
Bool_t HasOption(const char *key) const
Returns true if the given key appears in the URL options list.
Definition TUrl.cxx:685
small helper class to store/restore gPad context in TPad methods
Definition TVirtualPad.h:61
return c1
Definition legend1.C:41
TGraphErrors * gr
Definition legend1.C:25
@ kUseCompiledDefault
Use the compile-time default setting.
Definition Compression.h:53
TLine l
Definition textangle.C:4