@@ -511,6 +511,29 @@ Bool_t TRootSnifferFull::ProduceXml(const std::string &path, const std::string &
511511 return !res.empty ();
512512}
513513
514+ class TArgHolderBase : public TObject {
515+ public:
516+ TArgHolderBase () : TObject() {}
517+ virtual const void *GetPtr () const { return nullptr ; }
518+ };
519+
520+ template <typename T>
521+ class TArgHolder : public TArgHolderBase {
522+ public:
523+ T fValue ;
524+ TArgHolder (T v) : fValue (v) {}
525+ const void *GetPtr () const override { return &fValue ; }
526+ };
527+
528+ class TArgHolderConstChar : public TArgHolderBase {
529+ public:
530+ TString fValue ;
531+ const char *fBuf = nullptr ;
532+ TArgHolderConstChar (const char *v) : fValue (v) { fBuf = fValue .Data (); }
533+ const void *GetPtr () const override { return &fBuf ; }
534+ };
535+
536+
514537// //////////////////////////////////////////////////////////////////////////////
515538// / Execute command for specified object
516539// /
@@ -612,9 +635,18 @@ Bool_t TRootSnifferFull::ProduceExe(const std::string &path, const std::string &
612635 garbage.SetOwner (kTRUE ); // use as garbage collection
613636 TObject *post_obj = nullptr ; // object reconstructed from post request
614637 TString call_args;
638+ std::vector<const void *> plain_args;
639+ Bool_t can_use_plain = kTRUE , add_plain = kFALSE ;
640+
641+ auto add_plain_arg = [&plain_args, &garbage, &add_plain](TArgHolderBase *arg) {
642+ plain_args.emplace_back (arg->GetPtr ());
643+ garbage.Add (arg);
644+ add_plain = kTRUE ;
645+ };
615646
616647 TIter next (args);
617648 while (auto arg = static_cast <TMethodArg *>(next ())) {
649+ add_plain = kFALSE ;
618650
619651 if ((strcmp (arg->GetName (), " rest_url_opt" ) == 0 ) && (strcmp (arg->GetFullTypeName (), " const char*" ) == 0 ) &&
620652 (args->GetSize () == 1 )) {
@@ -628,6 +660,7 @@ Bool_t TRootSnifferFull::ProduceExe(const std::string &path, const std::string &
628660 call_args.Append (" \" " );
629661 call_args.Append (DecodeUrlOptionValue (rest_url, kTRUE ));
630662 call_args.Append (" \" " );
663+ add_plain_arg (new TArgHolderConstChar (rest_url));
631664 break ;
632665 }
633666
@@ -641,6 +674,7 @@ Bool_t TRootSnifferFull::ProduceExe(const std::string &path, const std::string &
641674 if (sval == " _this_" ) {
642675 // special case - object itself is used as argument
643676 sval.Form (" (%s*)0x%zx" , obj_cl->GetName (), (size_t )obj_ptr);
677+ add_plain_arg (new TArgHolder<void *>(obj_ptr));
644678 } else if ((fCurrentArg != nullptr ) && (fCurrentArg ->GetPostData () != nullptr )) {
645679 // process several arguments which are specific for post requests
646680 if (fAllowPostObject && (sval == " _post_object_xml_" )) {
@@ -653,6 +687,7 @@ Bool_t TRootSnifferFull::ProduceExe(const std::string &path, const std::string &
653687 if (url.HasOption (" _destroy_post_" ))
654688 garbage.Add (post_obj);
655689 }
690+ add_plain_arg (new TArgHolder<void *>(post_obj));
656691 } else if (fAllowPostObject && (sval == " _post_object_json_" )) {
657692 // post data has extra 0 at the end and can be used as null-terminated string
658693 post_obj = TBufferJSON::ConvertFromJSON ((const char *)fCurrentArg ->GetPostData ());
@@ -663,6 +698,7 @@ Bool_t TRootSnifferFull::ProduceExe(const std::string &path, const std::string &
663698 if (url.HasOption (" _destroy_post_" ))
664699 garbage.Add (post_obj);
665700 }
701+ add_plain_arg (new TArgHolder<void *>(post_obj));
666702 } else if (fAllowPostObject && (sval == " _post_object_" ) && url.HasOption (" _post_class_" )) {
667703 TString clname = DecodeUrlOptionValue (url.GetValueFromOptions (" _post_class_" ), kTRUE );
668704 TClass *arg_cl = gROOT ->GetClass (clname, kTRUE , kTRUE );
@@ -685,9 +721,11 @@ Bool_t TRootSnifferFull::ProduceExe(const std::string &path, const std::string &
685721 sval = " 0" ;
686722 else
687723 sval.Form (" (%s*)0x%zx" , clname.Data (), (size_t )post_obj);
688- } else if (sval == " _post_data_" )
724+ add_plain_arg (new TArgHolder<void *>(post_obj));
725+ } else if (sval == " _post_data_" ) {
689726 sval.Form (" (void*)0x%zx" , (size_t )fCurrentArg ->GetPostData ());
690- else if (sval == " _post_length_" )
727+ add_plain_arg (new TArgHolder<const void *>(fCurrentArg ->GetPostData ()));
728+ } else if (sval == " _post_length_" )
691729 sval.Form (" %ld" , (long )fCurrentArg ->GetPostDataLength ());
692730 else
693731 sanitize_numeric = kTRUE ;
@@ -705,6 +743,39 @@ Bool_t TRootSnifferFull::ProduceExe(const std::string &path, const std::string &
705743 if (call_args.Length () > 0 )
706744 call_args += " , " ;
707745
746+ if (!add_plain) {
747+ std::string tname = arg->GetTypeNormalizedName ();
748+ if (tname == " const char*" )
749+ // one can use original string, just remove optional quotes
750+ add_plain_arg (new TArgHolderConstChar (DecodeUrlOptionValue (val, kTRUE , kFALSE )));
751+ else if (tname == " bool" )
752+ add_plain_arg (new TArgHolder<bool >(!sval.IsNull () && (sval != " 0" ) && (sval != " false" )));
753+ else if (tname == " double" )
754+ add_plain_arg (new TArgHolder<double >(std::stod (sval.Data ())));
755+ else if (tname == " float" )
756+ add_plain_arg (new TArgHolder<float >(std::stof (sval.Data ())));
757+ else if (tname == " int" )
758+ add_plain_arg (new TArgHolder<int >(std::stol (sval.Data ())));
759+ else if (tname == " long" )
760+ add_plain_arg (new TArgHolder<long >(std::stol (sval.Data ())));
761+ else if (tname == " short" )
762+ add_plain_arg (new TArgHolder<short >(std::stol (sval.Data ())));
763+ else if (tname == " char" )
764+ add_plain_arg (new TArgHolder<char >(std::stol (sval.Data ())));
765+ else if (tname == " unsigned int" )
766+ add_plain_arg (new TArgHolder<unsigned int >(std::stoul (sval.Data ())));
767+ else if (tname == " unisgned long" )
768+ add_plain_arg (new TArgHolder<unsigned long >(std::stoul (sval.Data ())));
769+ else if (tname == " unsigned short" )
770+ add_plain_arg (new TArgHolder<unsigned short >(std::stoul (sval.Data ())));
771+ else if (tname == " unsigned char" )
772+ add_plain_arg (new TArgHolder<unsigned char >(std::stoul (sval.Data ())));
773+ else if (!tname.empty () && tname.back () == ' *' && (sval == " 0" || sval == " null" || sval == " nullptr" ))
774+ add_plain_arg (new TArgHolder<Longptr_t>(0 ));
775+ else
776+ can_use_plain = kFALSE ; // unsupported type, plain args cannot be used
777+ }
778+
708779 Bool_t isstr = (strcmp (arg->GetFullTypeName (), " const char*" ) == 0 ) ||
709780 (strcmp (arg->GetFullTypeName (), " Option_t*" ) == 0 ) ||
710781 (strcmp (arg->GetFullTypeName (), " string" ) == 0 );
@@ -741,7 +812,11 @@ Bool_t TRootSnifferFull::ProduceExe(const std::string &path, const std::string &
741812 TMethodCall *call = nullptr ;
742813
743814 if (method != nullptr ) {
744- call = new TMethodCall (obj_cl, method_name, call_args.Data ());
815+ if (can_use_plain) {
816+ call = new TMethodCall ();
817+ call->InitWithPrototype (obj_cl, method_name, prototype.IsNull () ? nullptr : prototype.Data ());
818+ } else
819+ call = new TMethodCall (obj_cl, method_name, call_args.Data ());
745820 if (debug)
746821 debug->append (TString::Format (" Calling obj->%s(%s);\n " , method_name, call_args.Data ()).Data ());
747822 } else {
@@ -771,10 +846,23 @@ Bool_t TRootSnifferFull::ProduceExe(const std::string &path, const std::string &
771846 garbage.Add (resbuf);
772847 }
773848
774- switch (call->ReturnType ()) {
849+ auto ret_type = call->ReturnType ();
850+ if (ret_type == TMethodCall::kOther ) {
851+ std::string ret_kind = func ? func->GetReturnTypeNormalizedName () : method->GetReturnTypeNormalizedName ();
852+ if ((ret_kind.length () > 0 ) && (ret_kind[ret_kind.length () - 1 ] == ' *' )) {
853+ ret_kind.resize (ret_kind.length () - 1 );
854+ ret_cl = gROOT ->GetClass (ret_kind.c_str (), kTRUE , kTRUE );
855+ }
856+ if (!ret_cl)
857+ ret_type = TMethodCall::kNone ;
858+ }
859+
860+ switch (ret_type) {
775861 case TMethodCall::kLong : {
776- Longptr_t l (0 );
777- if (method)
862+ Longptr_t l = 0 ;
863+ if (method && can_use_plain)
864+ call->Execute (obj_ptr, plain_args.data (), plain_args.size (), &l);
865+ else if (method)
778866 call->Execute (obj_ptr, l);
779867 else
780868 call->Execute (l);
@@ -785,8 +873,10 @@ Bool_t TRootSnifferFull::ProduceExe(const std::string &path, const std::string &
785873 break ;
786874 }
787875 case TMethodCall::kDouble : {
788- Double_t d (0 .);
789- if (method)
876+ Double_t d = 0 .;
877+ if (method && can_use_plain)
878+ call->Execute (obj_ptr, plain_args.data (), plain_args.size (), &d);
879+ else if (method)
790880 call->Execute (obj_ptr, d);
791881 else
792882 call->Execute (d);
@@ -798,7 +888,9 @@ Bool_t TRootSnifferFull::ProduceExe(const std::string &path, const std::string &
798888 }
799889 case TMethodCall::kString : {
800890 char *txt = nullptr ;
801- if (method)
891+ if (method && can_use_plain)
892+ call->Execute (obj_ptr, plain_args.data (), plain_args.size (), &txt);
893+ else if (method)
802894 call->Execute (obj_ptr, &txt);
803895 else
804896 call->Execute (&txt);
@@ -811,31 +903,21 @@ Bool_t TRootSnifferFull::ProduceExe(const std::string &path, const std::string &
811903 break ;
812904 }
813905 case TMethodCall::kOther : {
814- std::string ret_kind = func ? func->GetReturnTypeNormalizedName () : method->GetReturnTypeNormalizedName ();
815- if ((ret_kind.length () > 0 ) && (ret_kind[ret_kind.length () - 1 ] == ' *' )) {
816- ret_kind.resize (ret_kind.length () - 1 );
817- ret_cl = gROOT ->GetClass (ret_kind.c_str (), kTRUE , kTRUE );
818- }
819-
820- if (ret_cl != nullptr ) {
821- Longptr_t l (0 );
822- if (method)
823- call->Execute (obj_ptr, l);
824- else
825- call->Execute (l);
826- if (l != 0 )
827- ret_obj = (void *)l;
828- } else {
829- if (method)
830- call->Execute (obj_ptr);
831- else
832- call->Execute ();
833- }
834-
906+ Longptr_t l = 0 ;
907+ if (method && can_use_plain)
908+ call->Execute (obj_ptr, plain_args.data (), plain_args.size (), &l);
909+ else if (method)
910+ call->Execute (obj_ptr, l);
911+ else
912+ call->Execute (l);
913+ if (l != 0 )
914+ ret_obj = (void *)l;
835915 break ;
836916 }
837917 case TMethodCall::kNone : {
838- if (method)
918+ if (method && can_use_plain)
919+ call->Execute (obj_ptr, plain_args.data (), plain_args.size ());
920+ else if (method)
839921 call->Execute (obj_ptr);
840922 else
841923 call->Execute ();
0 commit comments