Classdesc  3.D29
xml_pack_base.h
Go to the documentation of this file.
1 /*
2  @copyright Russell Standish 2000-2013
3  @author Russell Standish
4  This file is part of Classdesc
5 
6  Open source licensed under the MIT license. See LICENSE for details.
7 */
8 
13 #ifndef XML_PACK_BASE_H
14 #define XML_PACK_BASE_H
15 #include <iostream>
16 #include <iomanip>
17 #include <sstream>
18 #include <string>
19 #include <assert.h>
20 
21 #include <classdesc.h>
22 #include <xml_common.h>
23 #include <stdexcept>
24 
25 namespace classdesc
26 {
27  inline std::string xml_quote(char c)
28  {
29  switch (c)
30  {
31  case '&': return "&amp;";
32  case '<': return "&lt;";
33  case '>': return "&gt;";
34  case '\'': return "&apos;";
35  case '"': return "&quot;";
36  }
37  if (!isgraph(c))
38  {
39  std::ostringstream s;
40  s<<"&#"<<int(c)<<";";
41  return s.str();
42  }
43  return std::string(1,c);
44  }
45 
49  class xml_pack_t
50  {
51  std::ostream* o; // weak reference, allows for assignability
52  int taglevel;
53  // count number of ids separated by '.'s in a string
54  int level(const string& xx) {
55  const char* x=xx.c_str();
56  int l;
57  if (*x=='\0') return 0;
58  for (l=1; *x!='\0'; x++) if (*x=='.') l++;
59  return l;
60  }
61 
62  void pretty(const string& d) {if (prettyPrint) *o << std::setw(level(d)) <<"";}
63  void endpretty() {if (prettyPrint) *o<<std::endl;}
64 
69  bool tag(const string& d) {
70  int l=level(d);
71  bool ret = taglevel < l; //return true if tag created
72  if (ret)
73  {
74  pretty(d);
75  *o<<"<"<<tail(d);
76  if (l==1 && !schema.empty())
77  *o<<" xmlns=\""<<schema<<"\"";
78  *o<<">";
79  endpretty();
80  taglevel=l;
81  }
82  assert(taglevel==level(d));
83  return ret;
84  }
86  void endtag(const string& d) {
87  taglevel--;
88  pretty(d);
89  *o<<"</"<<tail(d)<<">";
90  endpretty();
91  }
92 
93  friend class Tag;
94  public:
95  string schema;
96  bool prettyPrint;
97 
98  xml_pack_t(std::ostream& o, const string& schema=""):
99  o(&o), taglevel(0), schema(schema), prettyPrint(false) {}
100 
101  class Tag
102  {
103  xml_pack_t* t;
104  string d;
105  public:
106  Tag(xml_pack_t& t, const string& d): t(t.tag(d)? &t: 0), d(d) {}
107  ~Tag() {if (t) t->endtag(d);}
108  };
109 
113  template <class T>
114  void pack(const string& d, const T&x)
115  {
116  std::string tag=tail(d);
117  pretty(d);
118  *o << "<"<<tag<<">" << x << "</"<<tag<<">";
119  endpretty();
120  }
124  template <class T>
125  void pack_notag(const string& d, const T&x)
126  {/*pretty(d);*/ o<<x; /*endpretty();*/}
127 
128  };
129 
130  template <class T>
131  typename enable_if<is_fundamental<T>, void>::T
132  xml_packp(xml_pack_t& x,const string& d,T& a)
133  {x.pack(d,a);}
134 
135  template <> inline void xml_packp(xml_pack_t& x,const string& d, bool& a)
136  {x.pack(d, a? "true": "false");}
137 
142  template <class T>
143  typename enable_if<is_enum<T>, void>::T
144  xml_packp(xml_pack_t& x, const string& d, T& arg)
145  {x.pack(d,string(Enum_handle<T>(arg)));}
146 
147 }
148 
149 namespace classdesc_access
150 {
151  template <class T> struct access_xml_pack;
152 }
153 
154 template <class T> void xml_pack(classdesc::xml_pack_t&,const classdesc::string&, const T&);
155 
156 template <class T> void xml_pack(classdesc::xml_pack_t&,const classdesc::string&, T&);
157 
158 template <class T> classdesc::xml_pack_t& operator<<(classdesc::xml_pack_t& t, const T& a);
159 
160 inline void xml_pack(classdesc::xml_pack_t& x,const classdesc::string& d,
161  std::string& a)
162 {
163  std::string tmp;
164  for (std::string::size_type i=0; i<a.length(); i++) tmp+=classdesc::xml_quote(a[i]);
165  x.pack(d,tmp);
166 }
167 
168 inline void xml_pack(classdesc::xml_pack_t& x,const classdesc::string& d, const std::string& a)
169 {xml_pack(x,d,const_cast<std::string&>(a));}
170 
171 /* now define the array version */
172 #include <stdarg.h>
173 
174  template <class T> void xml_pack(classdesc::xml_pack_t& x,const classdesc::string& d,classdesc::is_array ia,
175  T& a, int dims,size_t ncopies,...)
176  {
177  va_list ap;
178  va_start(ap,ncopies);
179  for (int i=1; i<dims; i++) ncopies*=va_arg(ap,int); //assume that 2 and higher D arrays dimensions are int
180  va_end(ap);
182 
183  // element name is given by the type name
184  classdesc::string eName=classdesc::typeName<T>().c_str();
185  // strip leading namespace and qualifiers
186  const char *e=eName.c_str()+eName.length();
187  while (e!=eName.c_str() && *(e-1)!=' ' && *(e-1)!=':') e--;
188 
189  for (size_t i=0; i<ncopies; i++) xml_pack(x,d+"."+e,(&a)[i]);
190  }
191 
192 template <class T1, class T2>
193 void xml_pack(classdesc::xml_pack_t& x, const classdesc::string& d,
194  const std::pair<T1,T2>& arg)
195 {
197  xml_pack(x,d+".first",arg.first);
198  xml_pack(x,d+".second",arg.second);
199 }
200 
201 namespace classdesc
202 {
203  template <class T> typename
204  enable_if<Or<is_sequence<T>, is_associative_container<T> >, void>::T
205  xml_packp(xml_pack_t& x, const string& d, T& arg, dummy<1> dum=0)
206  {
207  xml_pack_t::Tag tag(x,d);
208  // element name is given by the type name
209  string eName=typeName<typename T::value_type>().c_str();
210  eName=eName.substr(0,eName.find('<')); //trim off any template args
211  // strip leading namespace and qualifiers
212  const char *e=eName.c_str()+eName.length();
213  while (e!=eName.c_str() && *(e-1)!=' ' && *(e-1)!=':') e--;
214 
215  for (typename T::const_iterator i=arg.begin(); i!=arg.end(); ++i)
216  ::xml_pack(x,d+"."+e,*i);
217  }
218 
219  template <class T>
220  void xml_pack_onbase(xml_pack_t& x,const string& d,T& a)
221  {::xml_pack(x,d+basename<T>(),a);}
222 
223 }
224 
225 using classdesc::xml_pack_onbase;
226 
227 /* member functions */
228 template<class C, class T>
229 void xml_pack(classdesc::xml_pack_t& targ, const classdesc::string& desc, C& c, T arg) {}
230 /* const static members */
231 template<class T>
232 void xml_pack(classdesc::xml_pack_t& targ, const classdesc::string& desc,
233  classdesc::is_const_static i, T arg)
234 {}
235 
236 template<class T, class U>
237 void xml_pack(classdesc::xml_pack_t& targ, const classdesc::string& desc,
238  classdesc::is_const_static i, const T&, U) {}
239 
240 template<class T>
241 void xml_pack(classdesc::xml_pack_t& targ, const classdesc::string& desc,
243 
244 // special handling of shared pointers to avoid a double wrapping problem
245 template<class T>
246 void xml_pack(classdesc::xml_pack_t& x, const classdesc::string& d,
247  classdesc::shared_ptr<T>& a);
248 
249 namespace classdesc
250 {
251  template<class T>
252  void xml_pack(xml_pack_t& targ, const string& desc, is_graphnode, T&)
253  {
254  throw exception("xml_pack of arbitrary graphs not supported");
255  }
256 
257 }
258 
259 #endif
Definition: classdesc.h:607
Definition: classdesc.h:610
Definition: xml_pack_base.h:49
xml_pack_t(std::ostream &o, const string &schema="")
if true, the layout XML in more human friendly form
Definition: xml_pack_base.h:98
Definition: classdesc.h:572
<utility structure for handling tag/endtag
Definition: xml_pack_base.h:101
void pack(const string &d, const T &x)
Definition: xml_pack_base.h:114
void pack_notag(const string &d, const T &x)
Definition: xml_pack_base.h:125
Definition: classdesc.h:688