Revision c44ca85a05174ee22a2137b47ae6cc944a8bb7cc authored by Ilka Antcheva on 27 February 2007, 10:52:09 UTC, committed by Ilka Antcheva on 27 February 2007, 10:52:09 UTC
GetFontByName() should really return 0 if it can't find the font
because there are none.


git-svn-id: http://root.cern.ch/svn/root/trunk@18094 27541ba8-7e3a-0410-8455-c3a389f83636
1 parent 301d93a
Raw File
DictionaryGenerator.cxx
// @(#)root/reflex:$Name:$:$Id:$
// Author: Antti Hahto   06/20/06

// Copyright CERN, CH-1211 Geneva 23, 2004-2006, All rights reserved.
//
// Permission to use, copy, modify, and distribute this software for any
// purpose is hereby granted without fee, provided that this copyright and
// permissions notice appear in all copies and derivatives.
//
// This software is provided "as is" without express or implied warranty.

#ifndef REFLEX_BUILD
#define REFLEX_BUILD
#endif


// DictGen, a replacement for genreflex.py
//================================================


#include "Reflex/DictionaryGenerator.h"
#include "Reflex/Member.h"
#include "Class.h"

// For adding the XML parser
//#include "TDOMParser.h"   
//#include "TXMLNode.h"

// USAGE:
// 
// 1. Create a new generator                        :  Dictgen generator
// 2. Set recursive parsing, optional (default:on)  :  generator.Use_recursive(true/false)
// 3. Set selection file,    optional               :  generator.Use_selection("filename")
// 4. Run, example
//      Scope::GlobalScope().GenerateDict(generator);
// 5. Dump results into file/stdout(if filename left empty)  : generator.Dump("filename")


using namespace std;

//-------------------------------------------------------------------------------
std::ostream & ROOT::Reflex::operator << ( std::ostream & s,
                                           const ROOT::Reflex::DictionaryGenerator & obj ) {
//-------------------------------------------------------------------------------

   time_t rawtime;
   time(&rawtime);

   s << "//Generated at " << ctime(&rawtime) << "//Do not modify." << endl << endl;
   s << "#include \"Reflex/Builder/ReflexBuilder.h\"" << endl;
   s << "#include <typeinfo>" << endl;
   s << "using namespace ROOT::Reflex;" << endl << endl;
   s << obj.fStr_header.str();
   
   s <<"namespace {" << endl;
   s << obj.fStr_namespaces.str();
   s << "}" << endl << endl;

   s << "// ---------------------- Shadow classes -----------------------------------" << endl;
   s << "namespace __shadow__ {" << endl;
   s << obj.fStr_shadow.str() << endl;
   s << "}" << endl << endl;
   
   s << "// ---------------------- Stub functions -----------------------------------" << endl;
   s << "namespace {" << endl;
   s << obj.fStr_classes.str();
   s << "} // unnamed namespace" << endl << endl;

   s << "// -------------------- Class dictionaries ---------------------------------" << endl;
   s << obj.fStr_frees.str();

   s << "// --------------------- Dictionary instances ------------------------------" << endl; 
   s << "namespace {" << endl;
   s << "  struct Dictionaries {" << endl;
   s << "    Dictionaries() {" << endl;
   s << obj.fStr_instances.str();
   s << "    }" << endl;
   s << "    ~Dictionaries() {" << endl;
   s << obj.fStr_instances2.str();
   s << "    }" << endl;
   s << "  };" << endl;
   s << "  static Dictionaries instance;" << endl;
   s << "}" << endl << endl;
   s << "// End of Dictionary" << endl;

   return s;

}



//-------------------------------------------------------------------------------
std::string ROOT::Reflex::DictionaryGenerator::Replace_colon(std::string scoped_name) {
//-------------------------------------------------------------------------------
// Replaces :: with __ , in a string
   std::string lname = scoped_name;
   for( unsigned i=0; i<lname.size(); ++i) {
      switch (lname[i]) {
      case '<':
      case '>':
      case ' ':
      case ',':
      case ':':
      case '.':
      case '*':
      case '(':
      case ')':
      case '&':
         lname[i] = '_';
         break;
      default:
         break;
      }
   }
   return lname;
}


//-------------------------------------------------------------------------------
bool ROOT::Reflex::DictionaryGenerator::Use_selection(const std::string & filename) {
//-------------------------------------------------------------------------------
// User defined selection file for classes to include
   std::ifstream infile;

   if (filename != "") {

      infile.open(filename.c_str());
      if (!infile.is_open()) {
         std::cout << "Error: Selection file not found!\n";
         infile.clear();
         return false;
      }

      std::cout << "\nUsing selection file:\n";
      std::string line = "";

      while (getline(infile, line)) {
         if (line.find("class name") != std::string::npos) {

            unsigned start = line.find("\"");
            unsigned end = line.rfind("\"/>");
            // cut the class name out of string
            line = line.substr(start + 1, end - start - 1);
            fSelections.push_back(line);
            std::cout << "searching for class " << line << "\n";
         }

         // <class pattern="ROOT::Reflex::*"/>
         if (line.find("class pattern") != std::string::npos) {

            unsigned start = line.find("=");
            unsigned end = line.rfind("*");
            line = line.substr(start + 2, end - start - 2);
            fPattern_selections.push_back(line);
            std::cout << "searching for class pattern " << line << "\n";
         }

      }
   
      
      /*   THIS IS HOWTO USE THE EXISTING XML-PARSER IN ROOT, TESTING

       TDOMParser parseri; 
       parseri.SetValidate(kFALSE);
  
       if( parseri.ParseFile("/home/ahahto/root2/test_selection.xml") !=0)
       {
       std::cerr<< "Error: no valid lcgdict XML file.\n";
       // return EXIT_FAILURE;
       }

       TXMLDocument *document = parseri.GetXMLDocument();
       TXMLNode *rootnode = document->GetRootNode();
      
       std::string rootnodename =  rootnode->GetNodeName();
       std::cout<<"Rootnode: ["<< rootnodename <<"]\n";

       if( rootnodename != "lcgdict")
       {
       std::cerr<< "Error: no valid lcgdict XML file.\n";
       // return EXIT_FAILURE;
       }

       //  TXMLNode *childnode = node->GetChildren();
       
       for ( TXMLNode *childnode = rootnode->GetChildren(); childnode !=0;  childnode = childnode ->GetNextNode())
       {  
       std::cout<< "\n* " << childnode->GetNodeName(); 

       if(childnode !=0) 
       {

       TList* lista =  childnode->GetAttributes();
       if(lista!=0) 
       {
       //TObject* objekti = lista -> First();
       for(TObject* objekti = lista -> First(); objekti !=0; objekti = lista -> After(objekti) )
       {
       if(objekti!=0) 
       {
       std::cout<< " [" << objekti ->GetName() <<"]";
       }
       }
       }
       }

       }
   */


   }

   return true;
}


//-------------------------------------------------------------------------------
bool ROOT::Reflex::DictionaryGenerator::Use_recursive(bool recursive) {
//-------------------------------------------------------------------------------
// Set the usage of recursive selection

   if (recursive == false) {
      fSelect_recursive = false;
   }

   if (recursive == true) {
      fSelect_recursive = true;
   }

   return true;
}


//-------------------------------------------------------------------------------
bool ROOT::Reflex::DictionaryGenerator::Use_recursive() {
//-------------------------------------------------------------------------------
// Returns, if selected recursive selection

   return fSelect_recursive;

}


//-------------------------------------------------------------------------------
bool ROOT::Reflex::DictionaryGenerator::IsNewType2(const Type & searchtype) {
//-------------------------------------------------------------------------------
// An optimized IsNewType, TESTING
/*   std::list < mydata >::iterator i =
      std::find_if(types2.begin(), types2.end(),
                   MatchItemNum(searchtype));

   if (i == types2.end()) {
      // not found
      return true;
   }

   else {
      //found
      return false;
   }
*/

// dummy return
   
   return searchtype;

}



//-------------------------------------------------------------------------------
bool ROOT::Reflex::DictionaryGenerator::IsNewType(const Type & searchtype) {
//-------------------------------------------------------------------------------
// Is the type already used somewhere
// This is used by GetTypeNumber

   /*  std::vector<ROOT::Reflex::Type>::iterator start = fTypes.begin();
       std::vector<ROOT::Reflex::Type>::iterator end = fTypes.end();
       std::vector<ROOT::Reflex::Type>::iterator iter;


       // pred is a comparing function used, IsEqual
       iter = find_if(start,end, searchtype, pred );


       if (iter == end)
       {
       // not found
       return true;

       }

       else
       {

       //found
       return false;
       }
   */

   for (unsigned k = 0; k < fTypes.size(); ++k) {

      if (fTypes.at(k) == searchtype) {
         return false;
      }
   }

   return true;
} // IsNewType



//-------------------------------------------------------------------------------
std::string ROOT::Reflex::DictionaryGenerator::GetParams(const Type & membertype) {
//-------------------------------------------------------------------------------
// Get params for the functions
   // Recursive, if it's a reference or a pointer
   if (membertype.IsReference()) {
      GetParams(membertype.ToType());
   }

   if (membertype.IsPointer()) {
      GetParams(membertype.ToType());
   }

   bool newtype = IsNewType(membertype);

   if (newtype) {
      // we add a new datamember not occurred before
      fTypes.push_back(membertype);

      //      types2.push_back(membertype);  //TESTING


      if (!membertype.IsFunction()) {
         // adding into NS this way
         GetTypeNumber(membertype);
      }
   }

   return membertype.Name();
}



//-------------------------------------------------------------------------------
std::string ROOT::Reflex::DictionaryGenerator::GetTypeNumber(const Type & membertype) {
//-------------------------------------------------------------------------------
// If a type is registered (eg.used) before,
// it has an unique ID-number returned as a string
// Also, add this type into NS field

   bool newtype = IsNewType(membertype);

   if (newtype) {
      // we add a new datamember not occurred before
      fTypes.push_back(membertype);
      //      types2.push_back(membertype);
   }

   std::stringstream numberstr;

   // get number
   for (unsigned k = 0; k < fTypes.size(); ++k) {

      if (fTypes.at(k) == membertype) {
         numberstr << k;
      }
   }

   // when it's a new type, add also into NS field
   // (No function members added)
   if (newtype && !(membertype.IsFunction())) {
      AddIntoNS(numberstr.str(), membertype);
   }

   return numberstr.str();
}

// GetTypeNumber



//-------------------------------------------------------------------------------
void ROOT::Reflex::DictionaryGenerator::AddIntoNS( const std::string & typenumber,
                                                   const Type & membertype ) {
//-------------------------------------------------------------------------------
// Namespaces field of the generated file

   if (fStr_namespaces.str() == "0") {
      //first item of the stream

      fStr_namespaces << "\nnamespace {  \n";
      fStr_namespaces << "Type type_void = TypeBuilder(\"void\");\n";
   }
   // Name(SCOPED)  adds also the namespace into name

   //     forward declarations
   if (membertype.TypeType() == STRUCT || membertype.TypeType() == CLASS
       || membertype.TypeType() == TYPEDEF) {
      fStr_shadow2 << (membertype).Name(SCOPED) << ";\n";
   }


   unsigned mod = 0;

   // if type is also a const, add that extra line
   // No references are supported by the original genreflex.py for datamembers!
   if (membertype.IsReference()) {
      if (membertype.IsConst())     mod |= CONST;
      if (membertype.IsVolatile())  mod |= VOLATILE;
      
      fStr_namespaces << "Type type_" + typenumber + " = ReferenceBuilder(type_" +
         GetTypeNumber(Type(membertype, mod)) + ");\n";
   }

   else if (membertype.IsConst()) {
      if (membertype.IsVolatile())   mod |= VOLATILE;

      fStr_namespaces << "Type type_" + typenumber +
         " = ConstBuilder(type_" + GetTypeNumber(Type(membertype, mod)) + ");\n";

   }


   else if (membertype.IsVolatile()) {

      fStr_namespaces << "Type type_" + typenumber + " = VolatileBuilder(type_" +
         GetTypeNumber(Type(membertype, mod)) + ");\n";

   }


   else if (membertype.TypeType() == CLASS) {

      fStr_namespaces << "Type type_" + typenumber + " = TypeBuilder(\"" + membertype.Name(SCOPED) + "\"); //class\n";
      //membertype
      fStr_instances2 << ("    type_" + typenumber + ".Unload(); //class " + (membertype).Name(SCOPED) + "\n");

   }

   else if (membertype.IsPointer()) {
      fStr_namespaces << "Type type_" + typenumber +
         " = PointerBuilder(type_" + GetTypeNumber(membertype.ToType()) + ");\n";
   }

   // void type
   else if (membertype.Name(SCOPED) == "") {
   }

   else {
      fStr_namespaces << "Type type_" + typenumber + " = TypeBuilder(\"" + membertype.Name(SCOPED) + "\");\n";

   }


} //AddIntoNS







//-------------------------------------------------------------------------------
void ROOT::Reflex::DictionaryGenerator::Print(const std::string & filename) {
//-------------------------------------------------------------------------------
// Outputs the results into standard stream / file

   if ( filename.length() ) {

      std::ofstream outfile(filename.c_str(), std::ios_base::out);

      if (!outfile.is_open()) {
         std::cout << "Error: Unable to write file!\n";
         outfile.clear();
      }
      else {
         outfile << *this;
         outfile.close();
      }


   } else {

      std::cout << "\n\n";
      std::cout << * this;

   }

} 



back to top