/* * Techno.cpp * DTR * * Created by damien dupuis on 01/04/10. * Copyright 2010 UPMC / LIP6. All rights reserved. * */ #include #include #include #include #include using namespace std; #include #include #include "io/dtr/Techno.h" #include "io/dtr/Rules.h" #include "io/dtr/DTRException.h" namespace { template 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) {} Rule* Techno::addRule (Name name, double value, Name ref, Name layer1, Name layer2) { Rule* rule = new Rule(name, value, ref, layer1, layer2); _rules.push_back(rule); return rule; } ARule* Techno::addARule (Name name, double value, Name ref, Name layer1, Name layer2) { ARule* arule = new ARule(name, value, ref, layer1, layer2); _rules.push_back(arule); return arule; } 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; for (size_t i = 0 ; i < _rules.size() ; i++) { Rule* rule = _rules[i]; if (rule->getName() == name) { 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: "); error += name.getString(); 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(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(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(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(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 << "" << endl << " " << endl; for (size_t i = 0 ; i < _rules.size() ; i++) { Rule* rule = _rules[i]; if (dynamic_cast(rule)) { file << " getName().getString() << "\" "; } else { file << " 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 << " " << endl << "" << endl; file.close(); return true; } }