LCOV - code coverage report
Current view: top level - builds/barbot/Cosmos/src/libgrml - expatmodelparser.cc (source / functions) Hit Total Coverage
Test: coverage.info Lines: 91 105 86.7 %
Date: 2021-06-16 15:43:28 Functions: 12 15 80.0 %

          Line data    Source code
       1             : #include "expatmodelparser.hh"
       2             : #include "tree/tree_util.hh"
       3             : #include <string>
       4             : 
       5             : 
       6             : 
       7           0 : IOError::IOError(std::string message) throw() : std::runtime_error(message) { }
       8             : 
       9           0 : ExpatError::ExpatError(XML_Error error_code) throw() : std::runtime_error(""), error_code(error_code) { }
      10           0 : const char* ExpatError::what() const throw()
      11             : {
      12           0 :     return XML_ErrorString(error_code);
      13             : }
      14             : 
      15          52 : ExpatModelParser::ExpatModelParser(ModelHandlerPtr h) : handler(h)
      16             : {
      17          52 :     parser = XML_ParserCreate(NULL);
      18          52 :     XML_SetUserData(parser, this);
      19             : 
      20          52 :     XML_SetStartElementHandler(parser, ExpatModelParser::on_start_element);
      21          52 :     XML_SetEndElementHandler(parser, ExpatModelParser::on_end_element);
      22          52 :     XML_SetCharacterDataHandler(parser, ExpatModelParser::on_characters);
      23          52 : }
      24             : 
      25         104 : ExpatModelParser::~ExpatModelParser()
      26             : {
      27          52 :     XML_ParserFree(parser);
      28          52 : }
      29             : 
      30          52 : void ExpatModelParser::parse_file(const std::string& filename)
      31             : {
      32         104 :     std::ifstream ifs(filename.c_str());
      33          52 :     if (ifs.fail()) {
      34           0 :         throw IOError("Cannot open the file");
      35             :     }
      36          52 :     parse_stream(ifs);
      37          52 : }
      38             : 
      39         226 : void ExpatModelParser::parse_stream(std::istream& in) 
      40             : {
      41             :     XML_Status status;
      42         400 :     while(in.good())
      43             :     {
      44         174 :         char* buffer = (char*) XML_GetBuffer(parser, BUFFER_SIZE);
      45         174 :         in.read(buffer, BUFFER_SIZE);
      46         174 :         status = XML_ParseBuffer(parser, in.gcount(), in.eof());
      47             : 
      48         174 :         if (status == XML_STATUS_ERROR)
      49             :         {
      50           0 :             XML_Error error_code = XML_GetErrorCode(parser);
      51           0 :             throw ExpatError(error_code);
      52             :         }
      53             :     }
      54          52 : }
      55             : 
      56       27309 : void ExpatModelParser::on_start_element(void *userData, const XML_Char *cname, const XML_Char **catts)
      57             : {
      58       27309 :     ExpatModelParser* self = (ExpatModelParser*) userData;
      59             : 
      60             :     // Convert c variables to c++ objects
      61       54618 :     XmlString name = cname;
      62       27309 :         size_t pos = name.find_last_of(":");
      63       27309 :         if (pos != std::string::npos)
      64           0 :                 name = name.substr(pos+1, name.size());
      65       54618 :     std::map<XmlString, XmlString> atts;
      66       66327 :     for(int i = 0; catts[i] != NULL; i +=2)
      67             :     {
      68       78036 :         XmlString attr_name = catts[i];
      69       78036 :         XmlString attr_value = catts[i + 1];
      70       39018 :         atts[attr_name] = attr_value;
      71             :     }
      72             : 
      73       27309 :     if (name == "model") { // <model>
      74          52 :         self->handler->on_read_model(atts["formalismUrl"]);
      75          52 :         self->state.push(MODEL);
      76             : 
      77       27257 :     } else if (name == "node") { // <node id= type= >
      78        1362 :         self->id = atts["id"];
      79        1362 :         self->type = atts["nodeType"];
      80        1362 :         self->attributes.clear();
      81        1362 :         self->references.clear();
      82        1362 :         self->state.push(NODE);
      83             : 
      84       25895 :     } else if (name == "arc") { // <arc id= type= source= target= >
      85        2669 :         self->id = atts["id"];
      86        2669 :         self->type = atts["arcType"];
      87        2669 :         self->source = atts["source"];
      88        2669 :         self->target = atts["target"];
      89        2669 :         self->attributes.clear();
      90        2669 :         self->references.clear();
      91        2669 :         self->state.push(ARC);
      92             : 
      93       23226 :     } else if (name == "attribute") { // <attribute name= >
      94       46452 :         std::string attributeName = atts["name"];
      95             : 
      96             :         // root GrML attribute
      97       23226 :         if (self->state.top() != ATTRIBUTE) {
      98        6511 :             self->attribute.clear();
      99        6511 :             self->attributeIterator = self->attribute.insert(self->attribute.begin(), attributeName);
     100             :         }
     101             : 
     102             :         // child GrML attribute
     103             :         else {
     104       16715 :             self->attributeIterator = self->attribute.append_child(self->attributeIterator, attributeName);
     105             :         }
     106             : 
     107       23226 :         self->xmlData.clear();
     108       23226 :         self->state.push(ATTRIBUTE);
     109           0 :     } else if (name == "ref") {
     110           0 :         self->references.push_back(atts["href"]);
     111             :     }
     112       27309 : }
     113             : 
     114       27309 : void ExpatModelParser::on_end_element(void *userData, const XML_Char *cname)
     115             : {
     116       27309 :     ExpatModelParser* self = (ExpatModelParser*) userData;
     117       54618 :     XmlString name = cname;
     118             :     try{
     119       27309 :         size_t pos = name.find_last_of(":");
     120       27309 :         if (pos != std::string::npos)
     121           0 :         name = name.substr(pos+1, name.size());
     122       27309 :         if (name == "model") { // </model>
     123          52 :             self->state.pop();
     124             : 
     125       27257 :         } else if (name == "node") { // </node>
     126        1362 :             self->state.pop();
     127        1362 :             self->handler->on_read_node(self->id, self->type, self->attributes, self->references);
     128             : 
     129       25895 :         } else if (name == "arc") { // </arc>
     130        2669 :             self->state.pop();
     131        2669 :             self->handler->on_read_arc(self->id, self->type, self->source, self->target, self->attributes, self->references);
     132             : 
     133       23226 :         } else if (name == "attribute") { // </attribute>
     134       23226 :             self->state.pop();
     135             : 
     136             :             // leaf node with data
     137       23226 :             if (!self->xmlData.empty() &&  self->attribute.number_of_children(self->attributeIterator) == 0) {
     138        9886 :                 self->trim(self->xmlData);
     139        9886 :                 self->attribute.append_child(self->attributeIterator, self->xmlData);
     140        9886 :                 self->xmlData.clear();
     141             :             }
     142             : 
     143             :             // root GrML attribute
     144       23226 :             if (self->state.top() == MODEL) {
     145         106 :                 self->handler->on_read_model_attribute(self->attribute);
     146       23120 :             } else if (self->state.top() == NODE || self->state.top() == ARC) {
     147        6405 :                 self->attributes[*self->attribute.begin()] = self->attribute;
     148             :             }
     149             : 
     150             :             // child GrML attribute
     151             :             else {
     152       16715 :                 self->attributeIterator = self->attribute.parent(self->attributeIterator);
     153             :             }
     154             :         }
     155           0 :     } catch (std::exception &e){
     156           0 :         std::cerr << "fail to parse '"+name+"' :"+e.what() << std::endl;
     157           0 :         exit(EXIT_FAILURE);
     158             :     }
     159       27309 : }
     160             : 
     161      102387 : void ExpatModelParser::on_characters(void *userData, const XML_Char *s, int len)
     162             : {
     163      102387 :     ExpatModelParser* self = (ExpatModelParser*) userData;
     164      102387 :     self->xmlData += std::string(s, len);
     165      102387 : }
     166             : 
     167        9886 : void ExpatModelParser::trim(std::string& s) {
     168       95640 :     s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](int c){return !std::isspace(c);}));
     169       79279 :     s.erase(std::find_if(s.rbegin(), s.rend(), [](int c){return !std::isspace(c);}).base(), s.end());
     170        9991 : }

Generated by: LCOV version 1.13