blitzdg
an open-source project aiming to implement parallel discontinuous Galerkin (dg) solvers for common partial differential equations systems using blitz++ for array and tensor manipulations and MPI for distributed parallelism.
xmlwriter.h
1 /*
2 Copyright (C) 2010, Ferruccio Barletta (ferruccio.barletta@gmail.com)
3 
4 Permission is hereby granted, free of charge, to any person
5 obtaining a copy of this software and associated documentation
6 files (the "Software"), to deal in the Software without
7 restriction, including without limitation the rights to use,
8 copy, modify, merge, publish, distribute, sublicense, and/or sell
9 copies of the Software, and to permit persons to whom the
10 Software is furnished to do so, subject to the following
11 conditions:
12 
13 The above copyright notice and this permission notice shall be
14 included in all copies or substantial portions of the Software.
15 
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18 OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 OTHER DEALINGS IN THE SOFTWARE.
24 */
25 #ifndef IGLOO_XMLWRITER_HPP
26 #define IGLOO_XMLWRITER_HPP
27 
28 #include <string>
29 #include <iostream>
30 #include <sstream>
31 #include <stack>
32 #include <cassert>
33 
34 namespace igloo {
35  class XmlElement;
36 
37  class XmlWriter
38  {
39  public:
40  // XmlWriter must be bound to an ostream
41  XmlWriter(std::ostream& os_) : os(os_) {
42  os << "<?xml version=\"1.0\" encoding=\"utf-8\"?>";
43  }
44  ~XmlWriter(void) { assert(elements.empty()); }
45 
46  private:
47  std::ostream& os; // output stream
48  std::stack<XmlElement*> elements; // stack of open element tags
49 
50  // write a single character to the output stream
51  XmlWriter& putc(char c) {
52  os.put(c);
53  return *this;
54  }
55 
56  // write a string to the output stream
57  XmlWriter& puts(const char* str) {
58  os << str;
59  return *this;
60  }
61 
62  friend class XmlElement;
63  };
64 
65  //
66  // XML element class
67  //
68  class XmlElement
69  {
70  public:
71  // create a new element tag, bound to an XmlWriter
72  XmlElement(const char* name_, XmlWriter& wr_) : name(name_), wr(wr_) {
73  assert(name != 0);
74  check_parent();
75  wr.putc('<').puts(name);
76  tagopen = true;
77  wr.elements.push(this);
78  }
79 
80  // close the current element tag
81  ~XmlElement() {
82  if (!wr.elements.empty() && wr.elements.top() == this) {
83  wr.elements.pop();
84  if (tagopen)
85  wr.puts("/>");
86  else
87  wr.puts("</").puts(name).putc('>');
88  }
89  }
90 
91  // write an attribute for the current element
92  XmlElement& attr(const char* attr_name, const char* value) {
93  assert(attr_name != 0);
94  assert(value != 0);
95  assert(tagopen);
96  wr.putc(' ').puts(attr_name).puts("=\"");
97  qputs(value);
98  wr.putc('"');
99  return *this;
100  }
101 
102  // attr() overload for std::string type
103  XmlElement& attr(const char* attr_name, const std::string& value) {
104  return attr(attr_name, value.c_str());
105  }
106 
107  // attr() function template for all streamable types
108  template <class T>
109  XmlElement& attr(const char* attr_name, T value) {
110  std::stringstream ss;
111  ss << value;
112  attr(attr_name, ss.str());
113  return *this;
114  }
115 
116  // write text content for the current element
117  XmlElement& contents(const char* str) {
118  assert(str != 0);
119  check_parent();
120  qputs(str);
121  return *this;
122  }
123 
124  // contents() overload for std::string type
125  XmlElement& contents(const std::string& str) {
126  return contents(str.c_str());
127  }
128 
129  // contents() function template for all streamable types
130  template <class T>
131  XmlElement& contents(T value) {
132  std::stringstream ss;
133  ss << value;
134  contents(ss.str());
135  return *this;
136  }
137 
138  // write CDATA section
139  XmlElement& cdata(const char* str) {
140  assert(str != 0);
141  check_parent();
142  wr.puts("<![CDATA[");
143  wr.puts(str);
144  wr.puts("]]>");
145  return *this;
146  }
147 
148  // cdata() overload for std::string type
149  XmlElement& cdata(const std::string& str) {
150  return cdata(str.c_str());
151  }
152  private:
153  const char* name; // name of current element
154  XmlWriter& wr; // bound XML writer
155  bool tagopen; // is the element tag for this element still open?
156 
157  // write a string quoting characters which have meaning in xml
158  XmlElement& qputs(const char* str) {
159  for (; *str; ++str)
160  switch (*str) {
161  case '&': wr.puts("&amp;"); break;
162  case '<': wr.puts("&lt;"); break;
163  case '>': wr.puts("&gt;"); break;
164  case '\'': wr.puts("&apos;"); break;
165  case '"': wr.puts("&quot;"); break;
166  default: wr.putc(*str); break;
167  }
168  return *this;
169  }
170 
171  // check to see if we have a parent tag which needs to be closed
172  void check_parent() {
173  if (!wr.elements.empty() && wr.elements.top()->tagopen) {
174  wr.putc('>');
175  wr.elements.top()->tagopen = false;
176  }
177  }
178  };
179 }
180 
181 #endif
Definition: xmlwriter.h:37
Definition: context.h:13
Definition: xmlwriter.h:68
Definition: choices.h:27