• Main Page
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

/export/development/ViennaGrid/release/ViennaGrid-1.0.0/viennagrid/io/xml_tag.hpp

Go to the documentation of this file.
00001 #ifndef VIENNAGRID_IO_XML_TAG_HPP
00002 #define VIENNAGRID_IO_XML_TAG_HPP
00003 
00004 /* =======================================================================
00005    Copyright (c) 2011, Institute for Microelectronics,
00006                        Institute for Analysis and Scientific Computing,
00007                        TU Wien.
00008 
00009                             -----------------
00010                      ViennaGrid - The Vienna Grid Library
00011                             -----------------
00012 
00013    Authors:      Karl Rupp                           rupp@iue.tuwien.ac.at
00014                  Josef Weinbub                    weinbub@iue.tuwien.ac.at
00015                
00016    (A list of additional contributors can be found in the PDF manual)
00017 
00018    License:      MIT (X11), see file LICENSE in the base directory
00019 ======================================================================= */
00020 
00021 
00026 #include <fstream>
00027 #include <iostream>
00028 #include <sstream>
00029 #include <list>
00030 #include <string>
00031 
00032 
00033 #include "viennagrid/io/helper.hpp"
00034 
00035 namespace viennagrid
00036 {
00037   namespace io
00038   {
00039     
00044     template <long dummy = 0>
00045     struct char_to_lower
00046     {
00047       char operator()(char c) const
00048       {
00049         if(c <= 'Z' && c >= 'A')
00050           return c - ('Z'-'z');
00051         return c;
00052       } 
00053     };
00054     
00059     template <typename StringType>                    //Note: Using artifically a template argument t
00060     StringType string_to_lower(StringType const & s)
00061     {
00062       std::string ret = s;
00063       std::transform(ret.begin(), ret.end(), ret.begin(), char_to_lower<0>());
00064       
00065       return ret;
00066     }
00067   
00072     template <typename dummy = bool> 
00073     class xml_tag
00074     {
00075         typedef std::pair<std::string, std::string>  AttributeType;
00076         typedef std::list<AttributeType>             AttributeContainer;
00077       
00078       public:
00079         
00081         template <typename InputStream>
00082         void parse(InputStream & reader)
00083         {
00084           reader.unsetf(std::ios_base::skipws);
00085           clear();
00086           
00087           char c = ' ';
00088           
00089           //go to start of tag:
00090           while (c != '<' && reader.good())
00091             reader >> c;
00092           
00093           //read tag name:
00094           while ( (c != ' ' && c != '>') && reader.good() )
00095           {
00096             reader >> c;
00097             name_.append(1,  make_lower(c));
00098           }
00099           
00100           //strip whitespace or closing tag at the end
00101           name_.resize(name_.size()-1);
00102           
00103           #ifdef VIENNAGRID_DEBUG_IO
00104           std::cout << name_ << std::endl;
00105           #endif
00106           
00107           if (c == '>') //we are all done
00108             return;
00109           
00110           //get attributes:
00111           bool end_of_attribute = false;
00112           bool inside_string = false;
00113           std::string token;
00114           while (c != '>' && reader.good())
00115           {
00116             reader >> c;
00117 
00118             if (inside_string && c == '"') //terminate string
00119             {
00120               end_of_attribute = true;
00121             }
00122             else if (!inside_string && c == '"') //start of string
00123             {
00124               inside_string = true;
00125             }
00126             else if (!inside_string && c == ' ')
00127             {
00128               //do nothing
00129               //throw bad_file_format_exception("filename", "Parse error: XML attribute ends prematurely.");
00130             }
00131 
00132             if (inside_string)
00133               token.append(1, c); //do not transform values to lower-case (e.g. filenames may get invalid)
00134             else if (c != ' ')
00135               token.append(1, make_lower(c));
00136             
00137             
00138             if (end_of_attribute)
00139             {
00140               std::size_t pos = token.find_first_of('=');
00141               if (pos == std::string::npos)
00142               {
00143                 throw bad_file_format_exception("filename", "Parse error: XML attribute does not have '=' sign.");
00144               }
00145               else if (pos == 0)
00146               {
00147                 throw bad_file_format_exception("filename", "Parse error: XML attribute name missing.");
00148               }
00149               
00150               
00151               std::string name = token.substr(0, pos);
00152               std::string value = token.substr(pos+2, token.size());
00153               
00154               pos = value.rfind('"');
00155               if (pos == std::string::npos || pos == 0)
00156                 throw bad_file_format_exception("filename", "Internal XML parse error: XML attribute string not terminated.");
00157               
00158               #ifdef VIENNAGRID_DEBUG_IO
00159               std::cout << name << ":" << value.substr(0, pos) << std::endl;
00160               #endif
00161               attributes_.push_back(std::make_pair(name, value.substr(0, pos)));
00162               
00163               token.clear();
00164               
00165               end_of_attribute = false;
00166               inside_string = false;
00167             }
00168           }
00169           
00170           reader.setf(std::ios_base::skipws);
00171         }
00172 
00174         void check_name(std::string const & expected_name,
00175                         std::string const & filename = std::string())
00176         {
00177           if (name_ != string_to_lower(expected_name))
00178           {
00179             std::stringstream ss;
00180             ss << "XML Parse error: " << expected_name << " expected, but got " << name_ << std::endl;
00181             throw bad_file_format_exception(filename,  ss.str());
00182           }
00183         }
00184 
00186         template <typename InputStream>
00187         void parse_and_check_name(InputStream & reader,
00188                                   std::string const & expected_name,
00189                                   std::string const & filename = std::string())
00190         {
00191           parse(reader);
00192           check_name(expected_name, filename);
00193         }
00194         
00196         std::string name() const { return name_; }
00197         
00199         bool has_attribute(std::string const & attrib_name) const
00200         {
00201           for (typename AttributeContainer::const_iterator it  = attributes_.begin();
00202                                                            it != attributes_.end();
00203                                                          ++it)
00204           {
00205             if (it->first == attrib_name)
00206               return true;
00207           }
00208           return false;
00209         }
00210 
00212         void check_attribute(std::string const & attrib_name,
00213                              std::string const & filename) const
00214         {
00215           if (!has_attribute(attrib_name))
00216           {
00217             std::stringstream ss;
00218             ss << "XML Parse error: Attribute " << attrib_name << " missing!" << std::endl;
00219             throw bad_file_format_exception(filename,  ss.str());
00220           }
00221         }        
00222         
00224         std::string get_value(std::string const & attrib_name) const
00225         {
00226           for (typename AttributeContainer::const_iterator it  = attributes_.begin();
00227                                                            it != attributes_.end();
00228                                                          ++it)
00229           {
00230             if (it->first == attrib_name)
00231               return it->second;
00232           }
00233           return "";
00234         }
00235         
00237         void clear()
00238         {
00239           name_ = std::string();
00240           attributes_.clear();
00241         }
00242       private:
00243         
00245         char make_lower(char c) const
00246         {
00247           if(c <= 'Z' && c >= 'A')
00248             return c - ('Z'-'z');
00249           return c;
00250         } 
00251 
00252         std::string name_;
00253         AttributeContainer attributes_;
00254     };
00255     
00256 
00257   } //namespace io
00258 } //namespace viennagrid
00259 
00260 #endif

Generated on Wed Sep 14 2011 19:21:30 for ViennaGrid by  doxygen 1.7.1