2010-04-03 10:52:29 -05:00
/*
* Techno . cpp
* DTR
*
* Created by damien dupuis on 01 / 04 / 10.
* Copyright 2010 UPMC / LIP6 . All rights reserved .
*
*/
# include <iostream>
# include <fstream>
# include <sstream>
# include <string>
# include <algorithm>
using namespace std ;
# include <libxml/parser.h>
# include <libxml/tree.h>
# include "io/dtr/Techno.h"
# include "io/dtr/Rules.h"
# include "io/dtr/DTRException.h"
namespace {
template < class T > T getValue ( xmlChar * str ) {
std : : istringstream iss ;
iss . str ( ( const char * ) str ) ;
T res ;
iss > > res ;
return res ;
}
}
namespace DTR {
Techno : : Techno ( Name name , Name unit ) : _name ( name ) , _unit ( unit ) { }
2010-04-05 11:27:18 -05:00
Rule * Techno : : addRule ( Name name , double value , Name ref , Name layer1 , Name layer2 ) {
Rule * rule = new Rule ( name , value , ref , layer1 , layer2 ) ;
2010-04-03 10:52:29 -05:00
_rules . push_back ( rule ) ;
return rule ;
}
2010-04-05 11:27:18 -05:00
ARule * Techno : : addARule ( Name name , double value , Name ref , Name layer1 , Name layer2 ) {
ARule * arule = new ARule ( name , value , ref , layer1 , layer2 ) ;
2010-04-03 10:52:29 -05:00
_rules . push_back ( arule ) ;
return arule ;
}
2010-04-05 11:27:18 -05:00
double Techno : : getValue ( Name name ) {
return getValue ( name , Name ( " " ) , Name ( " " ) ) ;
}
double Techno : : getValue ( Name name , Name layer ) {
return getValue ( name , layer , Name ( " " ) ) ;
}
double Techno : : getValue ( Name name , Name layer1 , Name layer2 ) {
bool testL1 = ( layer1 = = Name ( " " ) ) ? false : true ;
bool testL2 = ( layer2 = = Name ( " " ) ) ? false : true ;
2010-04-03 10:52:29 -05:00
for ( size_t i = 0 ; i < _rules . size ( ) ; i + + ) {
Rule * rule = _rules [ i ] ;
2010-04-05 11:27:18 -05:00
if ( rule - > getName ( ) = = name ) {
2010-04-03 10:52:29 -05:00
if ( testL1 ) {
if ( rule - > getLayer1 ( ) = = layer1 ) {
if ( testL2 ) {
if ( rule - > getLayer2 ( ) = = layer2 ) {
return rule - > getValue ( ) ;
}
} else {
return rule - > getValue ( ) ;
}
}
} else {
return rule - > getValue ( ) ;
}
}
}
string error ( " [ERROR] Could not found rule: " ) ;
2010-04-05 11:27:18 -05:00
error + = name . getString ( ) ;
2010-04-03 10:52:29 -05:00
error + = " . " ;
error + = layer1 . getString ( ) ;
error + = " . " ;
error + = layer2 . getString ( ) ;
error + = " . " ;
throw DTRException ( error ) ;
}
Techno * Techno : : readFromFile ( const string filePath ) {
LIBXML_TEST_VERSION ;
Techno * techno = NULL ;
xmlDoc * doc = xmlReadFile ( filePath . c_str ( ) , NULL , 0 ) ;
if ( doc = = NULL ) {
string error ( " [ERROR] Failed to parse: " ) ;
error + = filePath ;
throw DTRException ( error ) ;
//return NULL;
}
xmlNode * rootElement = xmlDocGetRootElement ( doc ) ;
if ( rootElement - > type = = XML_ELEMENT_NODE & & xmlStrEqual ( rootElement - > name , ( xmlChar * ) " technology " ) ) {
xmlChar * technoNameC = xmlGetProp ( rootElement , ( xmlChar * ) " name " ) ;
xmlChar * technoUnitC = xmlGetProp ( rootElement , ( xmlChar * ) " unit " ) ;
if ( technoNameC & & technoUnitC ) {
Name name ( ( const char * ) technoNameC ) ;
Name unit ( ( const char * ) technoUnitC ) ;
techno = new Techno ( name , unit ) ;
} else {
throw DTRException ( " [ERROR] 'technology' node must have 'name' and 'unit' properties. " ) ;
return NULL ;
}
xmlNode * child = rootElement - > children ;
for ( xmlNode * node = child ; node ; node = node - > next ) {
if ( node - > type = = XML_ELEMENT_NODE ) {
if ( ! xmlStrEqual ( node - > name , ( xmlChar * ) " physical_rules " ) ) {
throw DTRException ( " [ERROR] only 'physical_rules' node is allowed under 'technology' node. " ) ;
return NULL ;
}
for ( xmlNode * subnode = node - > children ; subnode ; subnode = subnode - > next ) {
if ( subnode - > type = = XML_ELEMENT_NODE ) {
if ( xmlStrEqual ( subnode - > name , ( xmlChar * ) " rule " ) ) {
xmlChar * nameC = xmlGetProp ( subnode , ( xmlChar * ) " name " ) ;
xmlChar * layerC = xmlGetProp ( subnode , ( xmlChar * ) " layer " ) ;
xmlChar * layer1C = xmlGetProp ( subnode , ( xmlChar * ) " layer1 " ) ;
xmlChar * layer2C = xmlGetProp ( subnode , ( xmlChar * ) " layer2 " ) ;
xmlChar * valueC = xmlGetProp ( subnode , ( xmlChar * ) " value " ) ;
xmlChar * refC = xmlGetProp ( subnode , ( xmlChar * ) " ref " ) ;
xmlChar * typeC = xmlGetProp ( subnode , ( xmlChar * ) " type " ) ;
Rule * rule = NULL ;
if ( nameC & & layer1C & & layer2C & & valueC & & refC ) { // rule with two layers
Name name ( ( const char * ) nameC ) ;
Name ref ( ( const char * ) refC ) ;
Name layer1 ( ( const char * ) layer1C ) ;
Name layer2 ( ( const char * ) layer2C ) ;
double value = : : getValue < double > ( valueC ) ;
rule = techno - > addRule ( name , value , ref , layer1 , layer2 ) ;
} else if ( nameC & & layerC & & valueC & & refC ) { // rule with only one layer
Name name ( ( const char * ) nameC ) ;
Name ref ( ( const char * ) refC ) ;
Name layer ( ( const char * ) layerC ) ;
double value = : : getValue < double > ( valueC ) ;
rule = techno - > addRule ( name , value , ref , layer ) ;
} else if ( nameC & & valueC & & refC ) { // rule without layer
Name name ( ( const char * ) nameC ) ;
Name ref ( ( const char * ) refC ) ;
double value = : : getValue < double > ( valueC ) ;
rule = techno - > addRule ( name , value , ref ) ;
} else { // invalid case
throw DTRException ( " [ERROR] properties of 'rule' node must be ('name', 'value', 'ref') or ( ' name ' , ' layer ' , ' value ' , ' ref ' ) or ( ' name ' , ' layer1 ' , ' layer2 ' , ' value ' , ' ref ' ) . " ) ;
return NULL ;
}
if ( typeC ) {
Name type ( ( const char * ) typeC ) ;
rule - > setType ( type ) ;
}
} else if ( xmlStrEqual ( subnode - > name , ( xmlChar * ) " arule " ) ) {
xmlChar * nameC = xmlGetProp ( subnode , ( xmlChar * ) " name " ) ;
xmlChar * layer1C = xmlGetProp ( subnode , ( xmlChar * ) " layer1 " ) ;
xmlChar * layer2C = xmlGetProp ( subnode , ( xmlChar * ) " layer2 " ) ;
xmlChar * valueC = xmlGetProp ( subnode , ( xmlChar * ) " value " ) ;
xmlChar * refC = xmlGetProp ( subnode , ( xmlChar * ) " ref " ) ;
if ( nameC & & layer1C & & layer2C & & valueC & & refC ) {
Name name ( ( const char * ) nameC ) ;
Name layer1 ( ( const char * ) layer1C ) ;
Name layer2 ( ( const char * ) layer2C ) ;
Name ref ( ( const char * ) refC ) ;
double value = : : getValue < double > ( valueC ) ;
techno - > addARule ( name , value , ref , layer1 , layer2 ) ;
} else {
throw DTRException ( " [ERROR] 'arule' node must have 'name', 'layer1', 'layer2', 'value' and 'ref' properties. " ) ;
return NULL ;
}
} else {
throw DTRException ( " [ERROR] only 'rule' and 'arule' nodes are allowed under 'physical_rules' node. " ) ;
}
}
}
}
}
}
return techno ;
}
bool Techno : : writeToFile ( string filePath ) {
ofstream file ;
file . open ( filePath . c_str ( ) ) ;
if ( ! file . is_open ( ) ) {
string error ( " [ERROR] Cannot open file " ) ;
error + = filePath ;
error + = " for writting. " ;
throw DTRException ( error ) ;
}
// checks before do anything
if ( _rules . size ( ) = = 0 ) {
throw DTRException ( " [ERROR] Cannot writeToFile since no rule is defined! " ) ;
}
file < < " <technology name= \" " < < _name . getString ( ) < < " \" unit= \" " < < _unit . getString ( ) < < " \" > " < < endl
< < " <physical_rules> " < < endl ;
for ( size_t i = 0 ; i < _rules . size ( ) ; i + + ) {
Rule * rule = _rules [ i ] ;
if ( dynamic_cast < ARule * > ( rule ) ) {
file < < " <arule name= \" " < < rule - > getName ( ) . getString ( ) < < " \" " ;
} else {
file < < " <rule name= \" " < < rule - > getName ( ) . getString ( ) < < " \" " ;
}
if ( rule - > getType ( ) ! = Name ( " " ) ) {
file < < " type= \" " < < rule - > getType ( ) . getString ( ) < < " \" " ;
}
if ( rule - > getLayer1 ( ) ! = Name ( " " ) ) {
if ( rule - > getLayer2 ( ) ! = Name ( " " ) ) {
file < < " layer1= \" " < < rule - > getLayer1 ( ) . getString ( ) < < " \" layer2= \" " < < rule - > getLayer2 ( ) . getString ( ) < < " \" " ;
} else {
file < < " layer= \" " < < rule - > getLayer1 ( ) . getString ( ) < < " \" " ;
}
}
file < < " value= \" " < < rule - > getValue ( ) < < " \" ref= \" " < < rule - > getRef ( ) . getString ( ) < < " \" /> " < < endl ;
}
file < < " </physical_rules> " < < endl
< < " </technology> " < < endl ;
file . close ( ) ;
return true ;
}
}