Source

mana-core-rootutils / src / PyROOTConstFix.cxx

Full commit
// $Id: PyROOTConstFix.cxx,v 1.1 2007-10-11 21:49:03 ssnyder Exp $
/**
 * @file RootUtils/src/PyROOTConstFix.cxx
 * @author scott snyder
 * @date Oct 2007
 * @brief Work around pyroot const bug.
 */

#include "RootUtils/PyROOTConstFix.h"
#include "TROOT.h"
#include "CallFunc.h"
#include "Class.h"
#include "Method.h"
#include "TBaseClass.h"
#include "TClass.h"


namespace RootUtils {


/**
 * @brief Fix one method.
 * @param classname The name of the class containing the method to fix.
 * @param funcname The name of the method to fix.
 *
 * Any const overload of the named method will have its name
 * overwritten in the cint dictionary, effectively hiding it from pyroot.
 */
void PyROOTConstFix::fix_one (const char* classname, const char* funcname)
{
  if (gROOT->GetClass (classname, kTRUE) == 0) return;

  G__ClassInfo ci (classname);
  if (!ci.IsValid()) return;

  G__MethodInfo gmi (ci);
  while (gmi.Next()) {
    if (strcmp (gmi.Name(), funcname) == 0) {
      // ??? Ignoring arg match here!!!!
      if (!(gmi.Property() & G__BIT_ISCONSTANT)) {
        // Trash the name so that PyROOT won't see it.
        char* nm = (char*)gmi.Name();
        while (*nm) {
          *nm++ = '#';
        }
      }
    }
  }
}


/**
 * @brief Fix all DataVector methods of a given class.
 * @param classname The name of the class to fix.
 *
 * This will apply @c fix_one to all of the DataVector methods
 * affected by this problem.
 */
void PyROOTConstFix::fix_all (const char* classname)
{
  fix_one (classname, "at");
  fix_one (classname, "front");
  fix_one (classname, "back");
  fix_one (classname, "begin");
  fix_one (classname, "end");
  fix_one (classname, "operator[]");
}


/*
 * @brief Test for a DataVector class and apply fix if needed.
 * @param classname The name of the class to test.
 * @returns True if the class or one of its bases was fixed, false otherwise.
 *
 * This function will test @c classname and any base classes
 * to see if they are DataVector classes.  If so, @c fix_all
 * will be applied to the class, and the function will return true.
 */
bool PyROOTConstFix::test_dv (const char* classname)
{
  // Use name rather than classname to handle typedefs properly.
  TClass* cl = gROOT->GetClass (classname, kTRUE);
  if (!cl) return false;
  const char* name = cl->GetName();

  // If it's a DataVector, fix it.
  if (strncmp (name, "DataVector<", 11) == 0) {
    fix_all (name);
    return true;
  }

  // Scan base classes too.
  TIter next (cl->GetListOfBases());
  while (TBaseClass* bcl = dynamic_cast<TBaseClass*>(next())) {
    TClass* cc = bcl->GetClassPointer();
    if (cc) {
      if (test_dv (cc->GetName()))
        return true;
    }
  }
  return false;
}


} // namespace RootUtils