<commit_before>// @(#)root/pyroot:$Id$
// Author: <NAME>, Apr 2004

// Bindings
#include "PyROOT.h"
#include "MethodHolder.h"
#include "Converters.h"
#include "Executors.h"
#include "ObjectProxy.h"
#include "RootWrapper.h"
#include "TPyException.h"
#include "Utility.h"
#include "Adapters.h"

// ROOT
#include "TROOT.h"
#include "TClass.h"
#include "TString.h"
#include "TClassEdit.h"
#include "TVirtualMutex.h"
#include "TException.h"
#include "TInterpreter.h"

// Standard
#include <assert.h>
#include <string.h>
#include <exception>
#include <string>


//- data and local helpers ---------------------------------------------------
R__EXTERN PyObject* gRootModule;

namespace {

   ClassInfo_t* GetGlobalNamespaceInfo() {
      return gInterpreter->ClassInfo_Factory();
   }

} // unnamed namespace


//- private helpers ----------------------------------------------------------
template< class T, class M >
inline void PyROOT::TMethodHolder< T, M >::Copy_( const TMethodHolder& other )
{
// do not copy caches
   fMethodCall = 0;
   fExecutor   = 0;

   fArgsRequired = -1;
   fOffset       =  0;

   fSignature = other.fSignature;

// being uninitialized will trigger setting up caches as appropriate
   fIsInitialized  = kFALSE;
}

//____________________________________________________________________________
template< class T, class M >
inline void PyROOT::TMethodHolder< T, M >::Destroy_() const
{
// no deletion of fMethod (ROOT responsibility)
   gInterpreter->CallFunc_Delete( fMethodCall );

// destroy executor and argument converters
   delete fExecutor;

   for ( int i = 0; i < (int)fConverters.size(); ++i )
      delete fConverters[ i ];
}

//____________________________________________________________________________
template< class T, class M >
inline PyObject* PyROOT::TMethodHolder< T, M >::CallFast( void* self, Bool_t release_gil )
{
// Helper code to prevent some duplication; this is called from CallSafe() as well
// as directly from TMethodHolder::Execute in fast mode.

   PyObject* result = 0;

// CLING WORKAROUND -- (#100390)
   if ( ! gInterpreter->CallFunc_IsValid( fMethodCall ) )
      return result;
// -- END CLING WORKAROUND

   try {       // C++ try block
      result = fExecutor->Execute( fMethodCall, (void*)((Long_t)self + fOffset), release_gil );
   } catch ( TPyException& ) {
      result = (PyObject*)TPyExceptionMagic;
   } catch ( std::exception& e ) {
      PyErr_Format( PyExc_Exception, "%s (C++ exception)", e.what() );
      result = 0;
   } catch ( ... ) {
      PyErr_SetString( PyExc_Exception, "unhandled, unknown C++ exception" );
      result = 0;
   }

   return result;
}

//____________________________________________________________________________
template< class T, class M >
inline PyObject* PyROOT::TMethodHolder< T, M >::CallSafe( void* self, Bool_t release_gil )
{
// Helper code to prevent some code duplication; this code embeds a ROOT "try/catch"
// block that saves the stack for restoration in case of an otherwise fatal signal.

   PyObject* result = 0;

   TRY {       // ROOT "try block"
      result = CallFast( self, release_gil );
   } CATCH( excode ) {
      PyErr_SetString( PyExc_SystemError, "problem in C++; program state has been reset" );
      result = 0;
      Throw( excode );
   } ENDTRY;

   return result;
}

//____________________________________________________________________________
template< class T, class M >
Bool_t PyROOT::TMethodHolder< T, M >::InitCallFunc_()
{
// build buffers for argument dispatching
   const size_t nArgs = fMethod.FunctionParameterSize();
   fConverters.resize( nArgs );
   fParameters.resize( nArgs );
   fParamPtrs.resize( nArgs );

// setup the dispatch cache
   std::string callString = "";
   for ( size_t iarg = 0; iarg < nArgs; ++iarg ) {
      std::string fullType =
         fMethod.TypeOf().FunctionParameterAt( iarg ).Name( Rflx::QUALIFIED | Rflx::SCOPED );
      fConverters[ iarg ] = CreateConverter( fullType );

      if ( ! fConverters[ iarg ] ) {
         PyErr_Format( PyExc_TypeError, "argument type %s not handled", fullType.c_str() );
         return kFALSE;
      }

   // setup call string
      if ( callString.length() == 0 )
         callString = fullType;
      else
         callString += ", " + fullType;
   }

// setup call func
   assert( fMethodCall == 0 );

   ClassInfo_t* gcl = ((TClass*)fClass.Id())->GetClassInfo();
   if ( ! gcl )
      gcl = GetGlobalNamespaceInfo();

// (CLING) TODO: this is NOT equal to the original CINT functionality, since it takes
// up a ConversionMatch, not an ExactMatch, but does that matter for Cling?
   fMethodCall = gInterpreter->CallFunc_Factory();
   gInterpreter->CallFunc_SetFuncProto(
      fMethodCall,
      gcl,
      (Bool_t)fMethod == true ? fMethod.Name().c_str() : fClass.Name().c_str(),<commit_msg>Cling workaround (#100392): massage argument type names<commit_after>// @(#)root/pyroot:$Id$
// Author: <NAME>, Apr 2004

// Bindings
#include "PyROOT.h"
#include "MethodHolder.h"
#include "Converters.h"
#include "Executors.h"
#include "ObjectProxy.h"
#include "RootWrapper.h"
#include "TPyException.h"
#include "Utility.h"
#include "Adapters.h"

// ROOT
#include "TROOT.h"
#include "TClass.h"
#include "TString.h"
#include "TClassEdit.h"
#include "TVirtualMutex.h"
#include "TException.h"
#include "TInterpreter.h"

// Standard
#include <assert.h>
#include <string.h>
#include <exception>
#include <string>


//- data and local helpers ---------------------------------------------------
R__EXTERN PyObject* gRootModule;

namespace {

   ClassInfo_t* GetGlobalNamespaceInfo() {
      return gInterpreter->ClassInfo_Factory();
   }

} // unnamed namespace


//- private helpers ----------------------------------------------------------
template< class T, class M >
inline void PyROOT::TMethodHolder< T, M >::Copy_( const TMethodHolder& other )
{
// do not copy caches
   fMethodCall = 0;
   fExecutor   = 0;

   fArgsRequired = -1;
   fOffset       =  0;

   fSignature = other.fSignature;

// being uninitialized will trigger setting up caches as appropriate
   fIsInitialized  = kFALSE;
}

//____________________________________________________________________________
template< class T, class M >
inline void PyROOT::TMethodHolder< T, M >::Destroy_() const
{
// no deletion of fMethod (ROOT responsibility)
   gInterpreter->CallFunc_Delete( fMethodCall );

// destroy executor and argument converters
   delete fExecutor;

   for ( int i = 0; i < (int)fConverters.size(); ++i )
      delete fConverters[ i ];
}

//____________________________________________________________________________
template< class T, class M >
inline PyObject* PyROOT::TMethodHolder< T, M >::CallFast( void* self, Bool_t release_gil )
{
// Helper code to prevent some duplication; this is called from CallSafe() as well
// as directly from TMethodHolder::Execute in fast mode.

   PyObject* result = 0;

// CLING WORKAROUND -- (#100390)
   if ( ! gInterpreter->CallFunc_IsValid( fMethodCall ) )
      return result;
// -- END CLING WORKAROUND

   try {       // C++ try block
      result = fExecutor->Execute( fMethodCall, (void*)((Long_t)self + fOffset), release_gil );
   } catch ( TPyException& ) {
      result = (PyObject*)TPyExceptionMagic;
   } catch ( std::exception& e ) {
      PyErr_Format( PyExc_Exception, "%s (C++ exception)", e.what() );
      result = 0;
   } catch ( ... ) {
      PyErr_SetString( PyExc_Exception, "unhandled, unknown C++ exception" );
      result = 0;
   }

   return result;
}

//____________________________________________________________________________
template< class T, class M >
inline PyObject* PyROOT::TMethodHolder< T, M >::CallSafe( void* self, Bool_t release_gil )
{
// Helper code to prevent some code duplication; this code embeds a ROOT "try/catch"
// block that saves the stack for restoration in case of an otherwise fatal signal.

   PyObject* result = 0;

   TRY {       // ROOT "try block"
      result = CallFast( self, release_gil );
   } CATCH( excode ) {
      PyErr_SetString( PyExc_SystemError, "problem in C++; program state has been reset" );
      result = 0;
      Throw( excode );
   } ENDTRY;

   return result;
}

//____________________________________________________________________________
template< class T, class M >
Bool_t PyROOT::TMethodHolder< T, M >::InitCallFunc_()
{
// build buffers for argument dispatching
   const size_t nArgs = fMethod.FunctionParameterSize();
   fConverters.resize( nArgs );
   fParameters.resize( nArgs );
   fParamPtrs.resize( nArgs );

// setup the dispatch cache
   std::string callString = "";
   for ( size_t iarg = 0; iarg < nArgs; ++iarg ) {
      std::string fullType =
         fMethod.TypeOf().FunctionParameterAt( iarg ).Name( Rflx::QUALIFIED | Rflx::SCOPED );
      fConverters[ iarg ] = CreateConverter( fullType );

      if ( ! fConverters[ iarg ] ) {
         PyErr_Format( PyExc_TypeError, "argument type %s not handled", fullType.c_str() );
         return kFALSE;
      }

   // CLING WORKAROUND --
   // See: #100392. If the template arguments exist in function arguments,
   // they are not filled in and the method won't be found.
      std::string::size_type pos = fullType.find("<_Tp,_Alloc>");
      if ( pos != std::string::npos ) {
         std::string klassName = fClass.Name();
         std::string::size_type pos1 = klassName.find( '<' );
         std::string::size_type pos2 = klassName.find( ',' );
         if (pos1 != std::string::npos) {
            fullType = fullType.substr(0, pos) +
                       klassName.substr( pos1, pos2-pos1 ) +
                       fullType.substr( pos + 12, std::string::npos );
         }
      }
   // -- END CLING WORKAROUND

   // setup call string
      if ( callString.length() == 0 )
         callString = fullType;
      else
         callString += ", " + fullType;
   }

// setup call func
   assert( fMethodCall == 0 );

   ClassInfo_t* gcl = ((TClass*)fClass.Id())->GetClassInfo();
   if ( ! gcl )
      gcl = GetGlobalNamespaceInfo();

// (CLING) TODO: this is NOT equal to the original CINT functionality, since it takes
// up a ConversionMatch, not an ExactMatch, but does that matter for Cling?
   fMethodCall = gInterpreter->CallFunc_Factory();
   gInterpreter->CallFunc_SetFuncProto(
      fMethodCall,
      gcl,
      (Bool_t)fMethod == true ? fMethod.Name().c_str() : fClass.Name().c_str(),
{'fraction_non_alphanumeric': 0.14179822872545245, 'fraction_numerical': 0.0064497497112052365, 'mean_word_length': 3.1144554455445546, 'pattern_counts': {'":': 0, '<': 39, '<?xml version=': 0, '>': 48, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7231592', 'n_tokens_mistral': 3239, 'n_tokens_neox': 3133, 'n_words': 897}