13 #ifndef XML_UNPACK_BASE_H 14 #define XML_UNPACK_BASE_H 23 #include "xml_common.h" 24 #include "classdesc.h" 31 template <
class T>
struct access_pack;
32 template <
class T>
struct access_unpack;
41 inline bool isspace(std::string s)
43 if (s.empty())
return false;
44 for (
size_t i=0; i<s.size(); i++)
45 if (!std::isspace(s[i]))
52 inline bool Isspace(
char c) {
return std::isspace(c)!=0;}
55 #pragma omit pack classdesc::XMLtoken 56 #pragma omit pack classdesc::xml_pack_error 57 #pragma omit unpack classdesc::XMLtoken 58 #pragma omit unpack classdesc::xml_pack_error 59 #pragma omit xml_pack classdesc::XMLtoken 60 #pragma omit xml_pack classdesc::xml_pack_error 61 #pragma omit xml_unpack classdesc::XMLtoken 62 #pragma omit xml_unpack classdesc::xml_pack_error 63 #pragma omit json_pack classdesc::xml_pack_error 64 #pragma omit json_unpack classdesc::xml_pack_error 65 #pragma omit dump classdesc::xml_pack_error 75 virtual const char* what()
const throw() {
return msg.c_str();}
79 inline bool get(std::istream& i,
char& c) {
return i.get(c).good();}
80 inline bool get(FILE*& i,
char& c)
81 {
int cc=fgetc(i); c=char(cc);
return cc!=EOF;}
82 inline void unget(std::istream& i,
char c) {i.putback(c);}
83 inline void unget(FILE*& i,
char c) {ungetc(c,i);}
85 template <
class Stream>
92 bool get(
char& c) {
return classdesc::get(i,c);}
93 void unget(
char c) {classdesc::unget(i,c);}
101 void gobble_comment();
102 void gobble_whitespace() {
105 while (notEof && std::isspace(c)) notEof=
get(c);
106 if (notEof) unget(c);
109 std::string retval(
char c,
const std::string& tok);
111 XMLtoken(Stream& i): i(i), nexttok(
'\0') {}
113 std::string tokenNoEOF() {
114 std::string tok=token();
120 template <
class Stream>
129 if (c==
'"') inString=!inString;
130 if (inString)
continue;
133 case '<': level++;
break;
134 case '>': level--;
break;
140 template <
class Stream>
145 for (c=getNoEOF(); c!=
';'; c=getNoEOF())
147 if (name==
"amp")
return '&';
148 if (name==
"lt")
return '<';
149 if (name==
"gt")
return '>';
150 if (name==
"quot")
return '"';
151 if (name==
"apos")
return '\'';
152 const char* cname=name.c_str();
158 long r=std::strtol(cname+2,NULL,16);
159 if (r>std::numeric_limits<char>::max() || r<std::numeric_limits<char>::min())
160 throw xml_pack_error(
"XML numeric character reference out of range");
166 long r=std::strtol(cname+1,NULL,10);
167 if (r>std::numeric_limits<char>::max() || r<std::numeric_limits<char>::min())
168 throw xml_pack_error(
"XML numeric character reference out of range");
177 template <
class Stream>
185 case '/':
return "</";
186 case '\\':
return "/>";
187 default:
return std::string(1,c);
197 template <
class Stream>
205 return retval(nexttok,tok);
210 if (std::isspace(c))
return retval(c,tok);
221 while ((c=getNoEOF())!=term)
234 gobble_comment();
continue;
236 return retval(
'/',tok);
240 return retval(
'<',tok);
244 if ((c=getNoEOF())==
'>')
245 return retval(
'\\',tok);
254 return retval(c,tok);
271 typedef std::map<std::string,std::string> ContentMap;
273 ContentMap contentMap;
274 std::map<std::string,unsigned> tokenCount;
276 void checkKey(
const std::string& key)
278 if (missingException && !contentMap.count(key))
283 std::string addHashNoughts(
const std::string& key)
286 std::string::size_type start=0, end;
287 bool hash_read=
false;
288 for (end=0; end<=key.length(); end++)
291 else if (key[end]==
'.')
297 r+=key.substr(start,end-start)+
"#0";
301 r+=key.substr(start,end-start);
313 xml_unpack_t(): missingException(false) {}
314 xml_unpack_t(
const char* fname): missingException(
false) {std::ifstream i(fname); parse(i);}
315 template <
class Stream> xml_unpack_t(Stream& i): missingException(
false) {parse(i);}
316 template <
class Stream>
void process_attribute(
XMLtoken<Stream>& i,
const std::string& scope);
317 template <
class Stream>
void parse(Stream& i);
318 template <
class Stream>
void parse(
XMLtoken<Stream>& stream,
const std::string& scope);
321 ContentMap::const_iterator
firstToken(
const std::string& prefix)
const {
322 return contentMap.lower_bound(prefix);
324 ContentMap::const_iterator endToken(
const std::string& prefix)
const {
325 return contentMap.upper_bound(prefix);
330 for (std::map<std::string,std::string>::const_iterator i=contentMap.begin();
331 i!=contentMap.end(); i++)
332 std::cout <<
"["<<i->first<<
"]="<<i->second<<std::endl;
333 std::cout << std::endl;
334 for (std::map<std::string,unsigned>::const_iterator i=tokenCount.begin();
335 i!=tokenCount.end(); i++)
336 std::cout <<
"Count["<<i->first<<
"]="<<i->second<<std::endl;
339 template <
class T>
void unpack(std::string key, T& var) {
340 key=addHashNoughts(key); checkKey(key);
341 std::map<std::string,std::string>::const_iterator it=contentMap.find(key);
342 if (it != contentMap.end()) {
343 std::istringstream s(it->second);
348 void unpack(std::string key,
bool& var) {
349 key=addHashNoughts(key); checkKey(key);
350 std::map<std::string,std::string>::const_iterator it=contentMap.find(key);
351 if (it != contentMap.end())
353 std::string val=it->second;
355 val.erase(remove_if(val.begin(), val.end(), Isspace), val.end());
356 for (
size_t i=0; i<val.length(); ++i) val[i]=
char(tolower(val[i]));
357 var = val==
"1" || val==
"t" || val==
"true"|| val==
"y"|| val==
"yes" ||
362 void unpack(std::string key, std::string& var) {
363 key=addHashNoughts(key); checkKey(key);
364 std::map<std::string,std::string>::const_iterator it=contentMap.find(key);
365 if (it != contentMap.end())
369 bool exists(
const std::string& key) {
return count(key)>0;}
372 key=addHashNoughts(key);
373 key=key.substr(0,key.rfind(
'#'));
374 return tokenCount[key];
376 void clear() {contentMap.clear(); tokenCount.clear();}
382 template <
class Stream>
386 while (isspace(tok=stream.tokenNoEOF()));
388 while (isspace(tok=stream.tokenNoEOF()));
389 contentMap[scope]=tok;
396 template <
class Stream>
397 void xml_unpack_t::parse(Stream& i)
401 while (isspace(tok=stream.token()));
402 if (tok.empty())
return;
404 parse(stream,stream.tokenNoEOF());
409 template <
class Stream>
410 void xml_unpack_t::parse(
XMLtoken<Stream>& stream,
const std::string& scope)
413 std::string scope_idx=
idx(scope,tokenCount[scope]++);
417 for (tok=stream.tokenNoEOF(); tok!=
">" && tok!=
"/>"; tok=stream.tokenNoEOF())
418 if (!isspace(tok)) process_attribute(stream, scope_idx+
"."+tok);
420 if (tok==
"/>")
return;
424 for (tok=stream.tokenNoEOF(); tok!=
"</"; tok=stream.tokenNoEOF())
426 parse(stream,scope_idx+
"."+stream.tokenNoEOF());
431 contentMap[scope_idx]=content;
434 tok=stream.tokenNoEOF();
435 if (scope.length()-scope.rfind(tok)!=tok.length())
437 for (; tok!=
">"; tok=stream.tokenNoEOF());
445 template <
class T>
struct access_xml_unpack;
458 void xml_unpack_onbase(
xml_unpack_t& x,
const string& d,T& a)
459 {::xml_unpack(x,d+basename<T>(),a);}
467 using classdesc::xml_unpack_onbase;
473 T& a,
int dims,
size_t ncopies,...)
476 va_start(ap,ncopies);
477 for (
int i=1; i<dims; i++) ncopies*=va_arg(ap,
int);
480 classdesc::string eName=classdesc::typeName<T>().c_str();
482 const char *e=eName.c_str()+eName.length();
483 while (e!=eName.c_str() && *(e-1)!=
' ' && *(e-1)!=
':') e--;
485 for (
size_t i=0; i<ncopies; i++)
491 const classdesc::string& d,
497 int (*isspace)(int)=std::isspace;
498 std::string::iterator end=std::remove_if(tmp.begin(),tmp.end(),isspace);
499 arg=tmp.substr(0,end-tmp.begin());
502 template <
class T1,
class T2>
504 std::pair<T1,T2>& arg)
506 xml_unpack(x,d+
".first",arg.first);
507 xml_unpack(x,d+
".second",arg.second);
512 template <
class T>
typename 516 string eName=typeName<typename T::value_type>().c_str();
517 eName=eName.substr(0,eName.find(
'<'));
519 const char *e=eName.c_str()+eName.length();
520 while (e!=eName.c_str() && *(e-1)!=
' ' && *(e-1)!=
':') e--;
523 for (
size_t i=0; i<x.
count(d+
"."+e); ++i)
525 typename T::value_type v;
531 template <
class T>
typename 535 string eName=typeName<typename T::value_type>().c_str();
536 eName=eName.substr(0,eName.find(
'<'));
538 const char *e=eName.c_str()+eName.length();
539 while (e!=eName.c_str() && *(e-1)!=
' ' && *(e-1)!=
':') e--;
542 string prefix=d.empty()? e: d+
"."+e;
543 for (
size_t i=0; i<x.
count(prefix); ++i)
545 typename NonConstKeyValueType<typename T::value_type>::T v;
546 ::xml_unpack(x,
idx(prefix,i),v);
553 template<
class C,
class T>
561 template<
class T,
class U>
574 throw exception(
"xml_unpack of arbitrary graphs not supported");
void unpack(std::string key, std::string &var)
string deserialisation
Definition: xml_unpack_base.h:362
Definition: xml_unpack_base.h:86
Definition: classdesc.h:631
Definition: classdesc.h:623
class to allow access to private members
Definition: classdesc_access.h:21
Definition: classdesc.h:626
Definition: xml_unpack_base.h:268
class to allow access to private members
Definition: classdesc_access.h:22
Definition: xml_unpack_base.h:68
ContentMap::const_iterator firstToken(const std::string &prefix) const
first token starting with prefix
Definition: xml_unpack_base.h:321
Definition: classdesc.h:588
void unpack(std::string key, T &var)
simple data type deserialisation
Definition: xml_unpack_base.h:339
std::string idx(const std::string &prefix, size_t i)
utility for generating index keys (for use with arrays)
Definition: xml_common.h:14
serialisation for standard containers
void printContentMap() const
dump XML contents for debugging
Definition: xml_unpack_base.h:329
Contains definitions related to classdesc functionality.
Definition: arrays.h:2514
controlled template specialisation: stolen from boost::enable_if.
Definition: classdesc.h:249
Definition: classdesc.h:266
Contains access_* structs, and nothing else. These structs are used to gain access to private members...
Definition: accessor.h:55
base class for exceptions thrown by classdesc
Definition: classdesc.h:366
size_t count(std::string key)
returns number of array elements with prefix key
Definition: xml_unpack_base.h:371
Definition: classdesc.h:704
bool missingException
Definition: xml_unpack_base.h:312
void unpack(unpack_t &targ, const string &desc, is_treenode dum, T *&arg)
unserialise a tree.
Definition: pack_graph.h:44
bool exists(const std::string &key)
checks for existence of token unpacked from XML stream
Definition: xml_unpack_base.h:369