Go to the documentation of this file.00001 #ifndef VIENNAGRID_IO_XML_TAG_HPP
00002 #define VIENNAGRID_IO_XML_TAG_HPP
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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>
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
00090 while (c != '<' && reader.good())
00091 reader >> c;
00092
00093
00094 while ( (c != ' ' && c != '>') && reader.good() )
00095 {
00096 reader >> c;
00097 name_.append(1, make_lower(c));
00098 }
00099
00100
00101 name_.resize(name_.size()-1);
00102
00103 #ifdef VIENNAGRID_DEBUG_IO
00104 std::cout << name_ << std::endl;
00105 #endif
00106
00107 if (c == '>')
00108 return;
00109
00110
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 == '"')
00119 {
00120 end_of_attribute = true;
00121 }
00122 else if (!inside_string && c == '"')
00123 {
00124 inside_string = true;
00125 }
00126 else if (!inside_string && c == ' ')
00127 {
00128
00129
00130 }
00131
00132 if (inside_string)
00133 token.append(1, c);
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 }
00258 }
00259
00260 #endif