Subversion Repositories HomeAutomation

Rev

Rev 1601 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | SVN | RSS feed

  1. /*
  2.  *
  3.  *  Copyright (C) 2010  Mattias Runge
  4.  *
  5.  *  This program is free software; you can redistribute it and/or modify
  6.  *  it under the terms of the GNU General Public License as published by
  7.  *  the Free Software Foundation; either version 2 of the License, or
  8.  *  (at your option) any later version.
  9.  *
  10.  *  This program is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  *  GNU General Public License for more details.
  14.  *
  15.  *  You should have received a copy of the GNU General Public License along
  16.  *  with this program; if not, write to the Free Software Foundation, Inc.,
  17.  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  18.  *
  19.  */
  20.  
  21. #include "Node.h"
  22.  
  23. //#include <iostream>
  24.  
  25. #include <fstream>
  26. #include <stdexcept>
  27.  
  28. #include <boost/lexical_cast.hpp>
  29. #include <boost/algorithm/string/trim.hpp>
  30.  
  31. namespace atom {
  32. namespace xml {
  33.  
  34. Node::Node()
  35. {
  36.  
  37. }
  38.  
  39. Node::~Node()
  40. {
  41.  
  42. }
  43.  
  44. void Node::LoadFile(std::string filename)
  45. {
  46.     std::ifstream srcfile(filename.data());
  47.        
  48.     if (!srcfile.is_open())
  49.     {
  50.         srcfile.close();
  51.         throw std::runtime_error("Could not find " + filename);
  52.         return;
  53.     }
  54.    
  55.     std::string buffer = "";
  56.     std::string line;
  57.    
  58.     while (!srcfile.eof())
  59.     {
  60.         std::getline(srcfile, line);
  61.        
  62.         if (srcfile.eof())
  63.         {
  64.             break;
  65.         }
  66.        
  67.         buffer += line + "\n";
  68.     }
  69.    
  70.     srcfile.close();
  71.    
  72.     this->Parse(buffer);
  73. }
  74.  
  75. void Node::Parse(std::string data)
  76. {
  77.     char c;
  78.     int position = 0;
  79.    
  80.     while ((unsigned int)position < data.length())
  81.     {
  82.         c = data.at(position);
  83.        
  84.         switch (c)
  85.         {
  86.             case '<':
  87.             {
  88.                 position = this->ParseTag(data, position);
  89.                 break;
  90.             }
  91.         }
  92.        
  93.         position++;
  94.     }
  95. }
  96.  
  97. int Node::ParseTag(std::string data, int position)
  98. {
  99.     if (data.at(position) != '<')
  100.     {
  101.         throw std::runtime_error("Id not find < as expected. Character " + boost::lexical_cast<std::string>(position));
  102.     }
  103.    
  104.     position++;
  105.    
  106.     int end_position = data.find('>', position);
  107.    
  108.     if (data.at(position) == '?' || data.at(position) == '!' || data.at(position) == '/')
  109.     {
  110.         return end_position;
  111.     }
  112.    
  113.     std::string tag_string;
  114.    
  115.     try
  116.     {
  117.         tag_string = data.substr(position, end_position - position);
  118.     }
  119.     catch (std::out_of_range& e)
  120.     {
  121.         throw std::runtime_error(e.what());
  122.     }
  123.    
  124.     boost::algorithm::trim(tag_string);
  125.     boost::algorithm::trim_if(tag_string, boost::is_any_of("\n"));
  126.     boost::algorithm::trim(tag_string);
  127.     tag_string += " ";
  128.    
  129.     bool found_end = false;
  130.     bool found_tag = false;
  131.     std::string buffer;
  132.     int pos = 0;
  133.     char c;
  134.     int s, e;
  135.    
  136.     while ((unsigned int)pos < tag_string.length())
  137.     {
  138.         c = tag_string.at(pos);
  139.        
  140.         switch (c)
  141.         {
  142.             case ' ':
  143.             {
  144.                 if (!found_tag)
  145.                 {
  146.                     this->tag_name_ = buffer;
  147.                     buffer = "";
  148.                     //std::cout << "Found tag: " << this->tag_name_ << std::endl;
  149.                     found_tag = true;
  150.                 }
  151.                 break;
  152.             }  
  153.             case '/':
  154.             {
  155.                 found_end = true;
  156.                 break;
  157.             }
  158.             case '=':
  159.             {
  160.                 s = tag_string.find('"', pos) + 1;
  161.                 e = tag_string.find('"', s);
  162.                
  163.                 try
  164.                 {
  165.                     this->attributes_[buffer] = tag_string.substr(s, e - s);
  166.                 }
  167.                 catch (std::out_of_range& ex)
  168.                 {
  169.                     throw std::runtime_error(ex.what());
  170.                 }
  171.  
  172.                 pos = e;
  173.                 buffer = "";
  174.                 break;
  175.             }
  176.             default:
  177.             {
  178.                 buffer += c;
  179.                 break;
  180.             }
  181.         }
  182.        
  183.         pos++;
  184.     }
  185.    
  186.     position = end_position;
  187.    
  188.     if (!found_end)
  189.     {
  190.         while ((unsigned int)position < data.length())
  191.         {
  192.             c = data.at(position);
  193.            
  194.             switch (c)
  195.             {
  196.                 case '<':
  197.                 {
  198.                     if (data.at(position+1) == '/')
  199.                     {
  200.                         position += 2;
  201.                         end_position = data.find('>', position);
  202.                        
  203.                         try
  204.                         {
  205.                             if (this->tag_name_.compare(data.substr(position, end_position - position)) == 0)
  206.                             {
  207.                                 //std::cout << "Found end tag: " << this->tag_name_ << std::endl;
  208.                                 return end_position;
  209.                             }
  210.                             else
  211.                             {
  212.                                 throw std::runtime_error("Invalid end tag found. " + data.substr(position, end_position - position) + "::" + this->tag_name_);
  213.                             }
  214.                         }
  215.                         catch (std::out_of_range& e)
  216.                         {
  217.                             throw std::runtime_error(e.what());
  218.                         }
  219.                        
  220.                        
  221.                     }
  222.                    
  223.                     Node sub_node;
  224.                     position = sub_node.ParseTag(data, position);
  225.                     this->children_.push_back(sub_node);
  226.                     break;
  227.                 }
  228.             }
  229.            
  230.             position++;
  231.         }
  232.     }
  233.    
  234.     return position;
  235. }
  236.  
  237. Node Node::FindChild(std::string tag_name)
  238. {
  239.     for (unsigned int n = 0; n < this->children_.size(); n++)
  240.     {
  241.         if (this->children_[n].GetTagName().compare(tag_name) == 0)
  242.         {
  243.             return this->children_[n];
  244.         }
  245.     }
  246.    
  247.     throw std::runtime_error("No child with that tag name found, " + tag_name);
  248. }
  249.  
  250. Node Node::SelectChild(std::string attribute_name, std::string attribute_value)
  251. {
  252.     for (unsigned int n = 0; n < this->children_.size(); n++)
  253.     {
  254.         if (this->children_[n].GetAttributeValue(attribute_name) == attribute_value)
  255.         {
  256.             return this->children_[n];
  257.         }
  258.     }
  259.    
  260.     throw std::runtime_error("No child with that attribute combination found, " + attribute_name + " = " + attribute_value);
  261. }
  262.  
  263. Node Node::SelectChild(std::string attribute_name1, std::string attribute_value1, std::string attribute_name2, std::string attribute_value2)
  264. {
  265.     for (unsigned int n = 0; n < this->children_.size(); n++)
  266.     {
  267.         if (this->children_[n].GetAttributeValue(attribute_name1) == attribute_value1 && this->children_[n].GetAttributeValue(attribute_name2) == attribute_value2)
  268.         {
  269.             return this->children_[n];
  270.         }
  271.     }
  272.    
  273.     throw std::runtime_error("No child with that attribute combination found, " + attribute_name1 + " = " + attribute_value1 + " && " + attribute_name2 + " = " + attribute_value2);
  274. }
  275.  
  276. std::string Node::GetAttributeValue(std::string attribute_name)
  277. {
  278.     AttributeList::const_iterator iterator = this->attributes_.find(attribute_name);
  279.    
  280.     if (iterator == this->attributes_.end())
  281.     {
  282.         throw std::runtime_error("No attribute with that name found, " + attribute_name);
  283.     }
  284.    
  285.     return iterator->second;
  286. }
  287.  
  288. Node::AttributeList Node::GetAttributes()
  289. {
  290.     return this->attributes_;
  291. }
  292.  
  293. std::vector<Node> Node::GetChildren()
  294. {
  295.     return this->children_;
  296. }
  297.  
  298. std::string Node::GetTagName()
  299. {
  300.     return this->tag_name_;
  301. }
  302.  
  303. }; // namespace xml
  304. }; // namespace atom
  305.