Universita' di GenovaINFN Sezione di Genova  
AIRWATCH / EUSO Genova

Config - source file

// ESAF : Euso Simulation and Analysis Framework
// $Id: Config.cc,v 1.20 2005/10/31 14:12:37 thea Exp $
// Author: Daniel De Marco    Jan, 25 2002
// M.Pallavicini - added Standard configuration handling 1/10/02

/*****************************************************************************
 * ESAF: Euso Simulation and Analysis Framework                              *
 *                                                                           *
 *  Id: EsafMsgDispatcher                                                    *
 *  Package: Base                                                            *
 *  Coordinator: Marco.Pallavicini                                           *
 *                                                                           *
 *****************************************************************************/

//______________________________________________________________________________
//  
//  Configuration Manager
//  ====================
//  
//


#include "Config.hh"
#include "StringsFileParser.hh"

#include <fstream>

ClassImp(Config)

Config *Config::fMe = 0;

//______________________________________________________________________________
 Config::Config() {
    // 
    // Ctor
    // 
    fCurrentConfig = "None";
    fStdConfigList = ConfigFileParser::GetCfgDir();
	fStdConfigList += "/Standard/StandardConfigs.lst";
    fCfgDump  = "./output/ConfigDump.cfg";
}

//______________________________________________________________________________
 Config::~Config() {
    // 
    // Dtor
    // 
}

//______________________________________________________________________________
 Config* Config::Get() {
    // 
    // Instance
    //
    if ( fMe == 0 ) 
        fMe = new Config();
    return fMe;
}

//______________________________________________________________________________
 void Config::SetCfgDump( const char* name ) {
    //
    //
    //

    if ( !name ) return;
    
    string ext = ".cfg";

    fCfgDump = name;

    if (fCfgDump.rfind(ext) != (fCfgDump.size()-ext.size()))
        fCfgDump += ext;
}

//______________________________________________________________________________
 void Config::SaveConfig( const char* name ) {
    //
    // Save the current configuration in a single "standard config file"
    //
    
    string fname = name ? name : fCfgDump; 
	ofstream of(fname.c_str(),ios::out
    if ( IsStandardConfigDefined() ) {
		of << "## Standard config " << fCurrentConfig << " is being used." << endl;
		of << "## user defined variables dump" << endl;
        map<string, vector<string>*>::iterator jt;
        for(jt=fUserDef.begin(); jt != fUserDef.end(); jt++) {
            of << "## Dump for class name " << jt->first << endl;

            vector<string>::iterator jt2;
            for(jt2 = jt->second->begin(); jt2 != jt->second->end(); jt2++)
                of << (*jt2) << endl;

            of << "## End of dump for class name " << jt->first << endl;
        }
		of.close();
		return;
	}
	of << "## config file dump generated by ESAF n\n";
	map<string, ConfigFileParser*>::const_iterator it;
	for(it=fCfs.begin(); it!=fCfs.end(); it++) {
		ConfigFileParser &cfp = *(it->second);
		of << "## Dump for class name " << it->first << endl;
		map<string,double>::const_iterator it2;
		for(it2=cfp.fNumbers.begin(); it2!=cfp.fNumbers.end(); it2++) {
			of << it2->first << " = " << it2->second << endl;
		}
		map<string,string>::const_iterator it3;
		for(it3=cfp.fChars.begin(); it3!=cfp.fChars.end(); it3++) {
			of << it3->first << " = " << it3->second << endl;
		}
		of << "## End of dump for class name " << it->first << endl;
	}
	of.close();
}

//______________________________________________________________________________
 ConfigFileParser *Config::GetCF(const string &ClassType, const string &ClassName,
                                const string &path ) {
    //
    // if ClassName is name of a parent class whose real instance is a child, the
    // file corresponding to the child is returned 
    //

	// if a standard config is defined, use it
	if ( IsStandardConfigDefined() )  {
		return fStandards[fCurrentConfig];
	}

	// check if this class has a child 
	string child_name;
	if ( fChildTable.count( ClassName ) == 0 ) 
		child_name = ClassName;
	else
		child_name = *(fChildTable[ClassName]);

    // create the ConfigFileParser if needed, and override parameters if required
    if ( fCfs.count(child_name) == 0 ) {
		fCfs[child_name] = new ConfigFileParser(ClassType,child_name,path);
        if ( fUserDef.count( child_name ) != 0 ) {
            vector<string>::iterator dummy;
            for( dummy = fUserDef[child_name]->begin();
                 dummy != fUserDef[child_name]->end() ;dummy++) 
                fCfs[child_name]->Replace( *dummy );
        }
	}

	// return ConfigFileParser
	return fCfs[child_name];
}

// handling standard configuration
// The file config/Standard/StandardConfigs.lst contains the names of the "Standard"
// configurations, i.e. files with all ESAF parameters.
// Each file will be also kept in the same directory


//______________________________________________________________________________
 Bool_t Config::UseConfig(const string& name) {
    // 
    // Define a new config with the current configuration files
    // to be implemented
    //

    if ( fStandards.count(name) == 0 ) {
        Msg(EsafMsg::Warning) << name << " is not defined as standard configuration in "
            << fStdConfigList<< MsgDispatch;
        return kFALSE;
    }
    
    Msg(EsafMsg::Info) << "Using standard configuration " << name << MsgDispatch;
    fCurrentConfig = name;
    return kTRUE;
}

//______________________________________________________________________________
 ConfigFileParser *Config::GetStandardConfig() {
    //
    // Get the current standard config if defined
    // returns NULL if not (no exception thrown)
    //
    if ( IsStandardConfigDefined() ) {
        if ( fStandards.find(fCurrentConfig) == fStandards.end() ) {
            Msg(EsafMsg::Warning) << "Standard config "+fCurrentConfig+" does not exist!!!" << MsgDispatch;
            return NULL;
        } else
            return fStandards[fCurrentConfig];
    }
    return (ConfigFileParser*)NULL;
}

//______________________________________________________________________________
 void Config::LoadStandardConfigs() {
    // 
    // Load the list of defined standard configs
    //

	// open file
	ifstream in(fStdConfigList.c_str());
	if(!in) FatalError("can't open file "+fStdConfigList);

	// get list from file
	// each line not beginning with # is considered a standard config name
	string dummy;
	while(getline(in, dummy)) {
		size_t pos;

        // erase comments
        pos=dummy.find('#');
        if(pos!=string::npos) dummy.erase(pos);
        
        // swallow spaces
        dummy=swallow_spaces(dummy);

        // skip blank lines
        if(dummy.empty()) continue;

        // now ready with name
        string cfgName = dummy;
        //FIXME: conflict with EsafMsgDispatcher building
        //Messages can't be used here
        //Msg(EsafMsg::Info) << "Reading standard config " << cfgName << MsgDispatch;
        Msg(EsafMsg::Info) << "Reading standard config " << cfgName << MsgDispatch;
       
		// build the ConfigFileParser object and put it into the map
		if ( fStandards.find(cfgName) == fStandards.end() ) {
			fStandards[cfgName] = new ConfigFileParser("Standard",cfgName);

			// override parameters if required
			// iterate on map elements
			map<string, vector<string>* >::iterator m_iter;
			for(m_iter = fUserDef.begin(); m_iter != fUserDef.end(); m_iter++) {
				// iterate on vector elements
				vector<string>::iterator v_iter;
				for(v_iter = m_iter->second->begin(); 
						v_iter != m_iter->second->end(); v_iter++) {
					fStandards[cfgName]->Replace(*v_iter);
				}
			}
		}
        else {
            //FIXME: conflict with EsafMsgDispatcher building
            //Messages can't be used here
            Msg(EsafMsg::Panic) << "Duplicate name "+cfgName+" in ./config/Standard/Config.cfg" << MsgDispatch;
        }
	}
}

//______________________________________________________________________________
 void Config::Reset(Bool_t user) {
    // 
    // Reset the config
    //
    
    // FIXME: check for memory leak here.
    // Does map destroy the elements it points to ?
	map<string,ConfigFileParser*>::iterator dummy;
	if (fCfs.size() != 0)
	for (dummy = fCfs.begin(); dummy != fCfs.end(); ++dummy)
		delete dummy->second;
	fCfs.clear();
    
    if ( user )
        ResetUserDef();
}

//______________________________________________________________________________
 void Config::ResetUserDef() {
    // 
	// Reset User settings
    //
	map<string, vector<string>* >::iterator dummy;
	if (fUserDef.size() != 0)
	for (dummy = fUserDef.begin(); dummy != fUserDef.end(); ++dummy)
		delete dummy->second;
	fUserDef.clear();
}

//______________________________________________________________________________
 void Config::AssociateParent(const string& c_name, const string& p_name) {
    // 
    // associate class name and parent name
    //
    if ( fChildTable.count(p_name) == 0 ) 
        fChildTable[p_name] = new string(c_name);
    else {
        if ( (*(fChildTable[p_name])) == c_name ) return;
        Msg(EsafMsg::Warning) << c_name << " is being associated to " 
            << p_name << endl;
        Msg(EsafMsg::Warning) <<  *(fChildTable[p_name]) << MsgDispatch; 
    }	     
}

//______________________________________________________________________________
 void Config::AddUserDefinition(const string &c_name, const string &expr) {
    //
    // Overrides a parameter of the config files.
    // Syntax:
    //  Config::Get()->AddUserDefinition( "classname","parameter=value")
    //

    string s = expr;
    s = swallow_spaces( s );
    if ( s.empty() )
        FatalError("invalid expr: "+expr);

    if ( fUserDef.count(c_name) == 0)
        fUserDef[c_name] = new vector<string>;

    fUserDef[c_name]->push_back(expr); 

	if ( IsStandardConfigDefined() &&  fUserDef.count( c_name ) != 0 )  
        fStandards[fCurrentConfig]->Replace( expr, kTRUE );
        
    MsgForm(EsafMsg::Debug,"UserDef added: class=%s, expr=%s",c_name.c_str(), expr.c_str());
}	

//______________________________________________________________________________
 Bool_t Config::LoadUserConfig( const char* fname ) {
    //
    // Load a set of user definitions from file
    // 
    // The definitions MUST have the following format
    // Classname.VarName=Value
    //

    StringsFileParser parser( fname );
    if ( parser.IsZombie() )
        MsgForm(EsafMsg::Panic,"File %s not found",fname);
    

    list< list<string> >& lines = parser.GetLines();

    size_t nlines = lines.size();
    size_t n(0);
    vector<string> keys(nlines);
    vector<string> expr(nlines);

    list<string>::const_iterator jt;
    list< list<string> >::const_iterator it;

    for( it = lines.begin(); it != lines.end(); it++ ) {
        // rebuild the line with 1 space
        string line;
        for (jt=it->begin(); jt != it->end();jt++ ) {
            if ( jt != it->begin() ) line += " "; 
            line += *(jt);
        }


        if ( it->size() != 3 ) {
            MsgForm(EsafMsg::Warning,"Wrong number of elements in file %s at line:",fname);
            Msg(EsafMsg::Panic) << line << "  " << it->size() << MsgDispatch;
            return kFALSE;
        }

        // keyword
        jt = it->begin();
        size_t pos = jt->find('.');

        if ( pos == string::npos ) {
            MsgForm(EsafMsg::Warning,"Corrupted file %s at line:",fname);
            Msg(EsafMsg::Panic) << line << "  " << it->size() << MsgDispatch;
            return kFALSE;
        }

        keys[n] = jt->substr(0,pos);

        // check on the '='
        jt++;
        if ( *(jt) != "=" ) {
            MsgForm(EsafMsg::Warning,"Corrupted file %s at line:",fname);
            Msg(EsafMsg::Panic) << line << "  " << it->size() << MsgDispatch;
            return kFALSE;
        }

        expr[n] = line;

        n++;
    }
    
    MsgForm(EsafMsg::Info,"UserConfig %s loaded.", fname);
    for (size_t i(0); i<n; i++)
        AddUserDefinition(keys[i],expr[i]);
   
    return kTRUE;
}
About Us | EUSO Official Website | Web pages created by Roberto Pesce and Alessandro Thea - Last Update Wed Nov 16 16:57:39 2005 Wed Nov 16 16:29:22 2005