libgenua
Basic Geometry, Numerical Algorithms and Interfaces
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Groups Pages
xmlelement.h
1 
2 /* Copyright (C) 2015 David Eller <david@larosterna.com>
3  *
4  * Commercial License Usage
5  * Licensees holding valid commercial licenses may use this file in accordance
6  * with the terms contained in their respective non-exclusive license agreement.
7  * For further information contact david@larosterna.com .
8  *
9  * GNU General Public License Usage
10  * Alternatively, this file may be used under the terms of the GNU General
11  * Public License version 3.0 as published by the Free Software Foundation and
12  * appearing in the file gpl.txt included in the packaging of this file.
13  */
14 
15 #ifndef GENUA_XMLELEMENT_H
16 #define GENUA_XMLELEMENT_H
17 
18 #include "forward.h"
19 #include "sharedvector.h"
20 #include "xcept.h"
21 #include "typecode.h"
22 #include "algo.h"
23 
24 #include <map>
25 #include <list>
26 #include <string>
27 #include <cstring>
28 #include <boost/shared_array.hpp>
29 
30 class ZipFile;
31 
61 {
62 public:
63 
65  enum StorageFormat {PlainText, ZippedXml, Lz4Compressed};
66 
68  typedef boost::shared_ptr<char[]> BlobType;
69 
70  typedef std::map<std::string, std::string> StringMap;
72  typedef ElementList::const_iterator const_iterator;
73  typedef ElementList::iterator mutable_iterator;
74  typedef StringMap::const_iterator attr_iterator;
75 
77  explicit XmlElement(const std::string & tg = "") : m_tag(tg), m_nbytes(0) {}
78 
80  explicit XmlElement(std::string && tg) : m_tag(std::move(tg)), m_nbytes(0) {}
81 
83  XmlElement(const std::string & tg, const std::string & content)
84  : m_tag(tg) {text(content);}
85 
88  m_tag(std::move(a.m_tag)), m_txt(std::move(a.m_txt)),
89  m_attributes(std::move(a.m_attributes)),
90  m_siblings(std::move(a.m_siblings)),
92  m_blob(std::move(a.m_blob)),
93  m_nbytes(a.m_nbytes) {}
94 
96  XmlElement(const XmlElement &) = default;
97 
100  if (&a != this) {
101  m_tag = std::move(a.m_tag);
102  m_txt = std::move(a.m_txt);
103  m_attributes = std::move(a.m_attributes);
104  m_siblings = std::move(a.m_siblings);
105  m_typecode = a.m_typecode;
106  m_blob = std::move(a.m_blob);
107  m_nbytes = a.m_nbytes;
108  }
109  return *this;
110  }
111 
113  XmlElement & operator= (const XmlElement &) = default;
114 
116  bool empty() const {
117  return (m_siblings.size() == 0) and m_attributes.empty() and
118  m_txt.empty() and (m_nbytes == 0);
119  }
120 
122  const std::string & name() const {return m_tag;}
123 
125  void rename(const std::string & s) {m_tag = s;}
126 
128  bool hasAttribute(const std::string & key) const
129  {return m_attributes.find(key) != m_attributes.end();}
130 
132  const std::string & attribute(const std::string & key) const;
133 
135  const std::string & attribute(const std::string & key,
136  const std::string & strDefault) const;
137 
139  attr_iterator attrBegin() const {return m_attributes.begin();}
140 
142  attr_iterator attrEnd() const {return m_attributes.end();}
143 
145  double attr2float(const std::string & key, double x) const;
146 
148  int attr2int(const std::string & key, int x) const;
149 
151  bool attr2bool(const std::string & key, bool x) const;
152 
154  template <class Streamable>
155  bool fromAttribute(const std::string & key, Streamable & sth) const
156  {
157  attr_iterator itr = m_attributes.find(key);
158  if (itr == m_attributes.end()) {
159  return false;
160  } else {
161  std::stringstream ss;
162  ss << itr->second;
163  ss >> sth;
164  }
165  return true;
166  }
167 
169  std::string & attribute(const std::string & key) {return m_attributes[key];}
170 
172  std::string & operator[] (const std::string & key) {return m_attributes[key];}
173 
175  const std::string & text() const {return m_txt;}
176 
178  std::string & text() {
179  m_nbytes = 0; m_typecode = TypeCode::None; m_blob.reset();
180  return m_txt;
181  }
182 
184  void text(const std::string & s) {
185  m_nbytes = 0;
186  m_typecode = TypeCode::None;
187  m_blob.reset();
188  m_txt=s;
189  }
190 
192  void text(const char *ptr, size_t n) {
193  m_nbytes = 0;
194  m_typecode = TypeCode::None;
195  m_blob.reset();
196  m_txt.assign(ptr, ptr+n);
197  }
198 
200  const_iterator begin() const {return m_siblings.begin();}
201 
203  const_iterator end() const {return m_siblings.end();}
204 
206  const_iterator findChild(const std::string & s) const;
207 
209  const XmlElement *findNode(const std::string & path) const;
210 
212  const XmlElement *findAnyTag(const std::string &tag) const;
213 
215  mutable_iterator mbegin() {return m_siblings.begin();}
216 
218  mutable_iterator mend() {return m_siblings.end();}
219 
221  size_t append(const XmlElement & c) {
222  m_siblings.push_back(c);
223  return m_siblings.size() - 1;
224  }
225 
227  size_t append(XmlElement &&c) {
228  m_siblings.push_back(std::move(c));
229  return m_siblings.size() - 1;
230  }
231 
233  size_t replaceAppend(const XmlElement &c);
234 
236  XmlElement & append(const std::string &childTag,
237  const std::string &childText = std::string());
238 
240  template <class ElementType>
241  XmlElement & append(const std::string &childTag,
242  size_t nvalues, const ElementType values[],
243  bool share = false)
244  {
245  XmlElement childElement(childTag);
246  childElement["count"] = std::to_string(nvalues);
247  childElement.asBinary(nvalues, values, share);
248  size_t idx = this->append( std::move(childElement) );
249  return m_siblings[idx];
250  }
251 
253  uint children() const {return m_siblings.size();}
254 
256  void eraseChild(uint k) {
257  m_siblings.erase( m_siblings.begin() + k );
258  }
259 
261  void replace(uint k, const XmlElement & xe) {
262  assert(k < m_siblings.size());
263  m_siblings[k] = xe;
264  }
265 
267  template <typename ScalarType>
268  void asBinary(size_t nval, const ScalarType a[], bool share = false) {
269  TypeCode tc = TypeCode::of<ScalarType>();
270  m_typecode = tc.value();
271  m_nbytes = nval * sizeof(ScalarType);
272  if (share) {
273  m_blob = BlobType((char *) a, null_deleter());
274  } else {
275  m_blob = BlobType(new char[m_nbytes]);
276  memcpy(&m_blob[0], a, m_nbytes);
277  }
278  m_attributes["bdata_bytes"] = std::to_string(m_nbytes);
279  m_attributes["bdata_type"] = TypeCode(m_typecode).toString();
280 
281  // default storage format is little endian
282  if (is_bigendian())
283  m_attributes["bdata_bigendian"] = "true";
284  }
285 
287  void fetch(size_t n, int a[]) const {
288  fetchAnything(n, a);
289  }
290 
292  void fetch(size_t n, uint a[]) const {
293  fetchAnything(n, a);
294  }
295 
297  void fetch(size_t n, int8_t a[]) const {
298  fetchAnything(n, a);
299  }
300 
302  void fetch(size_t n, uint8_t a[]) const {
303  fetchAnything(n, a);
304  }
305 
307  void fetch(size_t n, int16_t a[]) const {
308  fetchAnything(n, a);
309  }
310 
312  void fetch(size_t n, uint16_t a[]) const {
313  fetchAnything(n, a);
314  }
315 
317  void fetch(size_t n, int64_t a[]) const {
318  fetchAnything(n, a);
319  }
320 
322  void fetch(size_t n, uint64_t a[]) const {
323  fetchAnything(n, a);
324  }
325 
327  void fetch(size_t n, float a[]) const {
328  fetchAnything(n, a);
329  }
330 
332  void fetch(size_t n, double a[]) const {
333  fetchAnything(n, a);
334  }
335 
337  void fetch(size_t n, std::complex<float> a[]) const {
338  fetchAnything(2*n, (float *) a);
339  }
340 
342  void fetch(size_t n, std::complex<double> a[]) const {
343  fetchAnything(2*n, (double *) a);
344  }
345 
347  int blobType() const {return m_typecode;}
348 
350  const char *blobPointer() const {assert(m_blob); return &m_blob[0];}
351 
353  size_t blobBytes() const {return m_nbytes;}
354 
356  BlobType blob() const {return m_blob;}
357 
359  void shrink();
360 
362  void detach();
363 
365  bool read(std::istream &in, int format);
366 
368  bool write(std::ostream &os, int format) const;
369 
371  void read(const std::string & fname);
372 
374  void read(ZipFile & zf);
375 
377  void write(const std::string & fname, StorageFormat fmt) const;
378 
380  BinFileNodePtr toGbf(bool share = true) const;
381 
383  void fromGbf(const BinFileNodePtr &bfp, bool share=true);
384 
385 #ifdef HAVE_HDF5
386 
388  void toHdf5(Hdf5Group &parent) const;
389 
390 #endif
391 
392  // deprecated interface
393  void array2text(size_t n, const double a[]) {asBinary(n, a, false);}
394 
395  // deprecated interface
396  void array2text(size_t n, const float a[]) {asBinary(n, a, false);}
397 
398  // deprecated interface
399  void array2text(size_t n, const int a[]) {asBinary(n, a, false);}
400 
401  // deprecated interface
402  void array2text(size_t n, const uint a[]) {asBinary(n, a, false);}
403 
404  // deprecated interface
405  size_t text2array(size_t n, double a[]) const {fetch(n,a); return n;}
406 
407  // deprecated interface
408  size_t text2array(size_t n, float a[]) const {fetch(n,a); return n;}
409 
410  // deprecated interface
411  size_t text2array(size_t n, int a[]) const {fetch(n,a); return n;}
412 
413  // deprecated interface
414  size_t text2array(size_t n, uint a[]) const {fetch(n,a); return n;}
415 
417  void zwrite(const std::string & zfile, int compression = 1) const;
418 
420  void zread(const std::string & zfile);
421 
422 protected:
423 
425  void zwrite(std::ostream & xs, ZipFile & zf, uint indent) const;
426 
428  void zread(ZipFile & zf);
429 
431  void xwrite(const std::string & fname) const;
432 
434  void xread(std::istream & in);
435 
437  void xwrite(std::ostream & os, uint indent=0) const;
438 
440  template <typename Scalar>
441  void fetchAnything(size_t n, Scalar a[]) const {
442  if (m_nbytes > 0) {
443  TypeCode tc(m_typecode);
444  size_t nval = m_nbytes / tc.width();
445  if (nval < n)
446  throw Error("XmlElement::fetch() Requested more data than stored in this node.");
447 
448  if ( not tc.extract(nval, blobPointer(), a) )
449  throw Error(std::string("XmlElement::fetch() Type mismatch: ")
450  +tc.toString()+" != "+TypeCode::of<Scalar>().toString());
451 
452  } else if (not m_txt.empty()) {
453  const char *pos = m_txt.c_str();
454  char *tail(0);
455  size_t i;
456  for (i=0; i<n; ++i) {
457  if (not TypeCode::fromString(pos, &tail, a[i]))
458  break;
459  pos = tail;
460  }
461  if (i < n) {
462  std::string msg = "XmlElement::fetch(int) failed to find "
463  "enough elements in CDATA.";
464  msg += " Node: " + name() + " Expected: " + std::to_string(n)
465  + " Found: " + std::to_string(i);
466  msg += " Text: " + std::string(pos).substr(0, 6) + "...";
467  throw Error(msg);
468  }
469  }
470  }
471 
473  void binaryToText(std::ostream & os) const;
474 
475 private:
476 
478  std::string m_tag, m_txt;
479 
481  StringMap m_attributes;
482 
485 
488 
491 
493  size_t m_nbytes;
494 };
495 
496 
497 
498 #endif
Minimal frontend to zlib.
Definition: zipfile.h:34
XmlElement(XmlElement &&a)
move constructor (turns out MSVC doesn&#39;t auto-generate this one)
Definition: xmlelement.h:87
mutable_iterator mbegin()
iterate over children
Definition: xmlelement.h:215
BlobType blob() const
access shared pointer to block of binary data
Definition: xmlelement.h:356
void fetchAnything(size_t n, Scalar a[]) const
extract array from text content
Definition: xmlelement.h:441
void xread(std::istream &in)
read node recursively from plain text file, ignore binary data
Definition: xmlelement.cpp:379
void fetch(size_t n, int16_t a[]) const
universal access functions which use binary or text (exception on size mismatch)
Definition: xmlelement.h:307
std::string & text()
change text
Definition: xmlelement.h:178
const XmlElement * findNode(const std::string &path) const
find first node matching path, return 0 if not found
Definition: xmlelement.cpp:55
const char * blobPointer() const
access pointer to binary payload
Definition: xmlelement.h:350
bool write(std::ostream &os, int format) const
write to stream in specified format
Definition: xmlelement.cpp:211
int m_typecode
type of binary data included
Definition: xmlelement.h:487
void binaryToText(std::ostream &os) const
dump binary data to text stream
Definition: xmlelement.cpp:481
int value() const
access value
Definition: typecode.h:66
XmlElement & operator=(XmlElement &&a)
move assignment
Definition: xmlelement.h:99
double attr2float(const std::string &key, double x) const
if attribute present, convert to float, else return default
Definition: xmlelement.cpp:139
Group in HDF5 file.
Definition: hdf5file.h:251
void fetch(size_t n, int64_t a[]) const
universal access functions which use binary or text (exception on size mismatch)
Definition: xmlelement.h:317
void fetch(size_t n, uint a[]) const
universal access functions which use binary or text (exception on size mismatch)
Definition: xmlelement.h:292
void rename(const std::string &s)
change tag name
Definition: xmlelement.h:125
const_iterator findChild(const std::string &s) const
find first child with tag &quot;tg&quot;
Definition: xmlelement.cpp:46
int blobType() const
typecode for binary payload
Definition: xmlelement.h:347
void fromGbf(const BinFileNodePtr &bfp, bool share=true)
construct from GBF representation
Definition: xmlelement.cpp:759
bool empty() const
an element is empty if there are no children, attributes, nor payload
Definition: xmlelement.h:116
boost::shared_ptr< char[]> BlobType
storage for binary data
Definition: xmlelement.h:68
static TypeCode fromString(const std::string &s)
create type code from string
Definition: typecode.cpp:31
void fetch(size_t n, int8_t a[]) const
universal access functions which use binary or text (exception on size mismatch)
Definition: xmlelement.h:297
size_t append(const XmlElement &c)
append a child element
Definition: xmlelement.h:221
attr_iterator attrEnd() const
attribute iterator access
Definition: xmlelement.h:142
XmlElement(const std::string &tg, const std::string &content)
shortcut constructor for simple string elements
Definition: xmlelement.h:83
std::string & attribute(const std::string &key)
access attribute
Definition: xmlelement.h:169
void fetch(size_t n, std::complex< double > a[]) const
universal access functions which use binary or text (exception on size mismatch)
Definition: xmlelement.h:342
void detach()
make a deep copy of contained data
Definition: xmlelement.cpp:180
bool fromAttribute(const std::string &key, Streamable &sth) const
use std::stringstream to set attrbute only when present
Definition: xmlelement.h:155
void fetch(size_t n, uint16_t a[]) const
universal access functions which use binary or text (exception on size mismatch)
Definition: xmlelement.h:312
void zread(const std::string &zfile)
read from zip file
Definition: xmlelement.cpp:609
BinFileNodePtr toGbf(bool share=true) const
return GBF representation
Definition: xmlelement.cpp:725
attr_iterator attrBegin() const
attribute iterator access
Definition: xmlelement.h:139
mutable_iterator mend()
iterate over children
Definition: xmlelement.h:218
uint children() const
count child elements
Definition: xmlelement.h:253
void shrink()
shrink members to minimum size
Definition: xmlelement.cpp:166
void replace(uint k, const XmlElement &xe)
replace child element
Definition: xmlelement.h:261
Exception base class.
Definition: xcept.h:48
const std::string & name() const
access tag
Definition: xmlelement.h:122
std::string & operator[](const std::string &key)
access attribute
Definition: xmlelement.h:172
bool attr2bool(const std::string &key, bool x) const
if attribute present, convert to bool, else return default
Definition: xmlelement.cpp:157
bool extract(const char *raw, ValueType &x) const
convert from memory location to value
Definition: typecode.h:149
size_t append(XmlElement &&c)
append a child element
Definition: xmlelement.h:227
void xwrite(const std::string &fname) const
write root element to plain ascii xml file
Definition: xmlelement.cpp:248
bool hasAttribute(const std::string &key) const
check if attribute exists
Definition: xmlelement.h:128
int attr2int(const std::string &key, int x) const
if attribute present, convert to int, else return default
Definition: xmlelement.cpp:148
int width() const
width of the type in bytes
Definition: typecode.h:69
void eraseChild(uint k)
erase child element k
Definition: xmlelement.h:256
void fetch(size_t n, float a[]) const
universal access functions which use binary or text (exception on size mismatch)
Definition: xmlelement.h:327
XML Element.
Definition: xmlelement.h:60
void text(const char *ptr, size_t n)
change text
Definition: xmlelement.h:192
StorageFormat
supported on-disk file formats
Definition: xmlelement.h:65
bool read(std::istream &in, int format)
read from stream in specified format
Definition: xmlelement.cpp:190
const XmlElement * findAnyTag(const std::string &tag) const
find first element matching tag, using depth-first search
Definition: xmlelement.cpp:86
XmlElement(std::string &&tg)
create an element named tg, common case with temporary as tag
Definition: xmlelement.h:80
size_t m_nbytes
number of bytes stored
Definition: xmlelement.h:493
void fetch(size_t n, int a[]) const
universal access functions which use binary or text (exception on size mismatch)
Definition: xmlelement.h:287
const std::string & attribute(const std::string &key) const
access attribute
Definition: xmlelement.cpp:120
size_t replaceAppend(const XmlElement &c)
replace if already present, else append a child element
Definition: xmlelement.cpp:100
const char * toString() const
string representation of current code value
Definition: typecode.cpp:23
Integer type code.
Definition: typecode.h:38
BlobType m_blob
storage for binary data
Definition: xmlelement.h:490
StringMap m_attributes
attribute map
Definition: xmlelement.h:481
void zwrite(const std::string &zfile, int compression=1) const
store into zip file
Definition: xmlelement.cpp:526
const std::string & text() const
access text
Definition: xmlelement.h:175
void asBinary(size_t nval, const ScalarType a[], bool share=false)
register binary instead of character data payload, copy or link content
Definition: xmlelement.h:268
void fetch(size_t n, uint8_t a[]) const
universal access functions which use binary or text (exception on size mismatch)
Definition: xmlelement.h:302
std::string m_tag
tag name and enclosed text
Definition: xmlelement.h:478
XmlElement(const std::string &tg="")
create an element named tg
Definition: xmlelement.h:77
void fetch(size_t n, std::complex< float > a[]) const
universal access functions which use binary or text (exception on size mismatch)
Definition: xmlelement.h:337
const_iterator begin() const
iterate over children
Definition: xmlelement.h:200
size_t blobBytes() const
number of bytes in blob
Definition: xmlelement.h:353
void text(const std::string &s)
change text
Definition: xmlelement.h:184
void fetch(size_t n, double a[]) const
universal access functions which use binary or text (exception on size mismatch)
Definition: xmlelement.h:332
XmlElement & append(const std::string &childTag, size_t nvalues, const ElementType values[], bool share=false)
for convenience: Create an labeled child element containing vector data
Definition: xmlelement.h:241
void fetch(size_t n, uint64_t a[]) const
universal access functions which use binary or text (exception on size mismatch)
Definition: xmlelement.h:322
const_iterator end() const
iterate over children
Definition: xmlelement.h:203
ElementList m_siblings
children
Definition: xmlelement.h:484