13#ifndef CLASSDESC_XML_UNPACK_BASE_H
14#define CLASSDESC_XML_UNPACK_BASE_H
24#include "xml_common.h"
43 inline bool isspace(std::string s)
45 if (s.empty())
return false;
46 for (
size_t i=0; i<s.size(); i++)
47 if (!std::isspace(s[i]))
54 inline bool Isspace(
char c) {
return std::isspace(c)!=0;}
57#pragma omit pack classdesc::XMLtoken
58#pragma omit pack classdesc::xml_pack_error
59#pragma omit unpack classdesc::XMLtoken
60#pragma omit unpack classdesc::xml_pack_error
61#pragma omit xml_pack classdesc::XMLtoken
62#pragma omit xml_pack classdesc::xml_pack_error
63#pragma omit xml_unpack classdesc::XMLtoken
64#pragma omit xml_unpack classdesc::xml_pack_error
65#pragma omit json_pack classdesc::xml_pack_error
66#pragma omit json_unpack classdesc::xml_pack_error
67#pragma omit dump classdesc::xml_pack_error
70 class xml_pack_error :
public std::exception
74 xml_pack_error(
const char *s): msg(
"xml_pack:") {msg+=s;}
75 xml_pack_error(std::string s): msg(
"xml_pack:") {msg+=s;}
76 virtual ~xml_pack_error()
throw() {}
77 virtual const char* what()
const throw() {
return msg.c_str();}
81 inline bool get(std::istream& i,
char& c) {
return i.get(c).good();}
82 inline bool get(FILE*& i,
char& c)
83 {
int cc=fgetc(i); c=char(cc);
return cc!=EOF;}
84 inline void unget(std::istream& i,
char c) {i.putback(c);}
85 inline void unget(FILE*& i,
char c) {ungetc(c,i);}
87 template <
class Stream>
94 bool get(
char& c) {
return classdesc::get(i,c);}
95 void unget(
char c) {classdesc::unget(i,c);}
103 void gobble_comment();
104 void gobble_whitespace() {
107 while (notEof && std::isspace(c)) notEof=get(c);
108 if (notEof) unget(c);
111 std::string retval(
char c,
const std::string& tok);
113 XMLtoken(Stream& i): i(i), nexttok(
'\0') {}
115 std::string tokenNoEOF() {
116 std::string tok=token();
126 template <
class Stream>
127 void XMLtoken<Stream>::gobble_comment()
135 if (c==
'"') inString=!inString;
136 if (inString)
continue;
139 case '<': level++;
break;
140 case '>': level--;
break;
146 template <
class Stream>
147 char XMLtoken<Stream>::parse_entity()
151 for (c=getNoEOF(); c!=
';'; c=getNoEOF())
153 if (name==
"amp")
return '&';
154 if (name==
"lt")
return '<';
155 if (name==
"gt")
return '>';
156 if (name==
"quot")
return '"';
157 if (name==
"apos")
return '\'';
158 const char* cname=name.c_str();
164 long r=std::strtol(cname+2,NULL,16);
165 if (r>std::numeric_limits<char>::max() || r<std::numeric_limits<char>::min())
166 throw xml_pack_error(
"XML numeric character reference out of range");
172 long r=std::strtol(cname+1,NULL,10);
173 if (r>std::numeric_limits<char>::max() || r<std::numeric_limits<char>::min())
174 throw xml_pack_error(
"XML numeric character reference out of range");
183 template <
class Stream>
184 std::string XMLtoken<Stream>::retval(
char c,
const std::string& tok)
191 case '/':
return "</";
192 case '\\':
return "/>";
193 default:
return std::string(1,c);
203 template <
class Stream>
208 for (
int i=0; i<7; i++)
210 if (!get(c) || c==
'>')
break;
213 if (leadin==
"[CDATA[")
216 while ((c=getNoEOF()))
223 else if (c==
'>' && leadin==
"]]")
237 template <
class Stream>
245 gobble_comment();
return "";
247 return retval(
'/',tok);
250 return retval(
'<',tok);
254 template <
class Stream>
255 std::string XMLtoken<Stream>::token()
262 return retval(nexttok,tok);
267 if (std::isspace(c))
return retval(c,tok);
278 while ((c=getNoEOF())!=term)
287 std::string r=processOpenXMLTag(tok);
288 if (r.empty())
continue;
292 if ((c=getNoEOF())==
'>')
293 return retval(
'\\',tok);
302 return retval(c,tok);
319 typedef std::map<std::string,std::string> ContentMap;
322 ContentMap contentMap;
323 std::map<std::string,unsigned> tokenCount;
325 void checkKey(
const std::string& key)
332 std::string addHashNoughts(
const std::string& key)
335 std::string::size_type start=0, end;
336 bool hash_read=
false;
337 for (end=0; end<=key.length(); end++)
340 else if (key[end]==
'.')
346 r+=key.substr(start,end-start)+
"#0";
350 r+=key.substr(start,end-start);
365 template <
class Stream>
void process_attribute(XMLtoken<Stream>& i,
const std::string& scope);
366 template <
class Stream>
void parse(Stream& i);
367 template <
class Stream>
void parse(XMLtoken<Stream>& stream,
const std::string& scope);
370 ContentMap::const_iterator
firstToken(
const std::string& prefix)
const {
371 return contentMap.lower_bound(prefix);
373 ContentMap::const_iterator endToken(
const std::string& prefix)
const {
374 return contentMap.upper_bound(prefix);
379 for (std::map<std::string,std::string>::const_iterator i=contentMap.begin();
380 i!=contentMap.end(); i++)
381 std::cout <<
"["<<i->first<<
"]="<<i->second<<std::endl;
382 std::cout << std::endl;
383 for (std::map<std::string,unsigned>::const_iterator i=tokenCount.begin();
384 i!=tokenCount.end(); i++)
385 std::cout <<
"Count["<<i->first<<
"]="<<i->second<<std::endl;
390 template <
class T>
void istoT(
const std::string& s,
T& x)
392 std::istringstream is(s);
395#if defined(__cplusplus) && __cplusplus>=201103L
396 void stoT(
const std::string& s,
float& x)
397 try {x=std::stof(s);}
398 catch(...){istoT(s,x);}
399 void stoT(
const std::string& s,
double& x)
400 try {x=std::stod(s);}
401 catch(...){istoT(s,x);}
402 void stoT(
const std::string& s,
long double& x)
403 try {x=std::stold(s);}
404 catch(...){istoT(s,x);}
406 template <
class T>
void stoT(
const std::string& s, T& x)
410 template <
class T>
void unpack(std::string key,
T& var) {
411 key=addHashNoughts(key); checkKey(key);
412 std::map<std::string,std::string>::const_iterator it=contentMap.find(key);
413 if (it != contentMap.end()) stoT(it->second, var);
416 void unpack(std::string key,
bool& var) {
417 key=addHashNoughts(key); checkKey(key);
418 std::map<std::string,std::string>::const_iterator it=contentMap.find(key);
419 if (it != contentMap.end())
421 std::string val=it->second;
423 val.erase(remove_if(val.begin(), val.end(), Isspace), val.end());
424 for (
size_t i=0; i<val.length(); ++i) val[i]=
char(tolower(val[i]));
425 var = val==
"1" || val==
"t" || val==
"true"|| val==
"y"|| val==
"yes" ||
430 void unpack(std::string key, std::string& var) {
431 key=addHashNoughts(key); checkKey(key);
432 std::map<std::string,std::string>::const_iterator it=contentMap.find(key);
433 if (it != contentMap.end())
437 {
unpack(key,
static_cast<std::string&
>(a));}
443 key=addHashNoughts(key);
444 key=key.substr(0,key.rfind(
'#'));
445 return tokenCount[key];
447 void clear() {contentMap.clear(); tokenCount.clear();}
453 template <
class Stream>
457 while (isspace(tok=stream.tokenNoEOF()));
459 while (isspace(tok=stream.tokenNoEOF()));
460 contentMap[scope]=tok;
467 template <
class Stream>
472 while (isspace(tok=stream.token()));
473 if (tok.empty())
return;
475 parse(stream,stream.tokenNoEOF());
480 template <
class Stream>
484 std::string scope_idx=
idx(scope,tokenCount[scope]++);
488 for (tok=stream.tokenNoEOF(); tok!=
">" && tok!=
"/>"; tok=stream.tokenNoEOF())
491 if (tok==
"/>")
return;
495 for (tok=stream.tokenNoEOF(); tok!=
"</"; tok=stream.tokenNoEOF())
497 parse(stream,scope_idx+
"."+stream.tokenNoEOF());
502 contentMap[scope_idx]=content;
505 tok=stream.tokenNoEOF();
506 if (scope.length()-scope.rfind(tok)!=tok.length())
508 for (; tok!=
">"; tok=stream.tokenNoEOF());
515 template <
class T>
void xml_unpack(xml_unpack_t&,
const string&,T&);
517 template <
class T> xml_unpack_t& operator>>(xml_unpack_t& t, T& a);
523 void xml_unpack_onbase(xml_unpack_t& x,
const string& d,T& a)
533 T& a,
int dims,
size_t ncopies,...)
536 va_start(ap,ncopies);
537 for (
int i=1; i<dims; i++) ncopies*=va_arg(ap,
int);
540 classdesc::string eName=classdesc::typeName<T>().c_str();
542 const char *e=eName.c_str()+eName.length();
543 while (e!=eName.c_str() && *(e-1)!=
' ' && *(e-1)!=
':') e--;
545 for (
size_t i=0; i<ncopies; i++)
555 int (*isspace)(int)=std::isspace;
556 std::string::iterator end=std::remove_if(tmp.begin(),tmp.end(),isspace);
557 arg=tmp.substr(0,end-tmp.begin());
560 template <
class T1,
class T2>
561 void xml_unpack(
xml_unpack_t& x,
const string& d, std::pair<T1,T2>& arg)
563 xml_unpack(x,d+
".first",arg.first);
564 xml_unpack(x,d+
".second",arg.second);
567 template <
class T>
typename
571 string eName=typeName<typename T::value_type>().c_str();
572 eName=eName.substr(0,eName.find(
'<'));
574 const char *e=eName.c_str()+eName.length();
575 while (e!=eName.c_str() && *(e-1)!=
' ' && *(e-1)!=
':') e--;
577 size_t cnt=x.count(d+
"."+e);
581 for (
typename T::iterator j=arg.begin(); i<cnt && j!=arg.end(); ++i, ++j)
582 xml_unpack(x,
idx(d+
"."+e,i),*j);
585 template <
class T>
typename
589 string eName=typeName<typename T::value_type>().c_str();
590 eName=eName.substr(0,eName.find(
'<'));
592 const char *e=eName.c_str()+eName.length();
593 while (e!=eName.c_str() && *(e-1)!=
' ' && *(e-1)!=
':') e--;
596 string prefix=d.empty()? e: d+
"."+e;
597 for (
size_t i=0; i<x.count(prefix); ++i)
599 typename NonConstKeyValueType<typename T::value_type>::T v;
600 xml_unpack(x,
idx(prefix,i),v);
617 {targ.unpack(desc,a);}
622 throw exception(
"xml_unpack of arbitrary graphs not supported");
628#include "use_mbr_pointers.h"
629CLASSDESC_USE_OLDSTYLE_MEMBER_OBJECTS(xml_unpack)
630CLASSDESC_FUNCTION_NOP(xml_unpack)
632using classdesc::xml_unpack;
633using classdesc::xml_unpack_onbase;
Definition classdesc.h:868
Definition xml_unpack_base.h:89
std::string processOpenXMLTag(std::string &)
handle XML tags ('<' case)
Definition xml_unpack_base.h:238
std::string processBang(std::string &tok, char c)
handle tags starting with ! - comments and CDATAs
Definition xml_unpack_base.h:204
Definition classdesc.h:920
Definition classdesc.h:923
Definition classdesc.h:931
Definition xml_unpack_base.h:71
Definition xml_unpack_base.h:317
void printContentMap() const
dump XML contents for debugging
Definition xml_unpack_base.h:378
ContentMap::const_iterator firstToken(const std::string &prefix) const
first token starting with prefix
Definition xml_unpack_base.h:370
void process_attribute(XMLtoken< Stream > &i, const std::string &scope)
Definition xml_unpack_base.h:454
void parse(Stream &i)
Definition xml_unpack_base.h:468
void unpack(std::string key, std::string &var)
string deserialisation
Definition xml_unpack_base.h:430
bool missingException
Definition xml_unpack_base.h:361
size_t count(std::string key)
returns number of array elements with prefix key
Definition xml_unpack_base.h:442
void unpack(std::string key, T &var)
simple data type deserialisation
Definition xml_unpack_base.h:410
bool exists(const std::string &key)
checks for existence of token unpacked from XML stream
Definition xml_unpack_base.h:440
descriptor access to a class's privates
#define CLASSDESC_ACCESS(type)
add friend statements for each accessor function
Definition classdesc_access.h:36
Contains access_* structs, and nothing else. These structs are used to gain access to private members...
Definition classdesc_access.h:20
Contains definitions related to classdesc functionality.
std::string idx(const std::string &prefix, size_t i)
utility for generating index keys (for use with arrays)
Definition xml_common.h:14
string basename()
returns a valid identifier to append to the descriptor of a base class
Definition classdesc.h:1127
serialisation for standard containers
used to transfer contents of CDATA sections.
Definition xml_common.h:23
Definition classdesc.h:1012
Definition classdesc.h:299
controlled template specialisation: stolen from boost::enable_if.
Definition classdesc.h:282
base class for exceptions thrown by classdesc
Definition classdesc.h:546
class to allow access to private members
Definition classdesc_access.h:21
class to allow access to private members
Definition classdesc_access.h:22