1 #pragma once 2 /* 3 * DataElement/DataNode/DataTree -- structured serialization/deserialization system 4 * designed for the CoolMule project :) 5 * 6 Copyright (C) 2003 by Charles J. Cliffe 7 8 Permission is hereby granted, free of charge, to any person obtaining a copy 9 of this software and associated documentation files (the "Software"), to deal 10 in the Software without restriction, including without limitation the rights 11 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 copies of the Software, and to permit persons to whom the Software is 13 furnished to do so, subject to the following conditions: 14 15 The above copyright notice and this permission notice shall be included in 16 all copies or substantial portions of the Software. 17 18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 THE SOFTWARE. 25 */ 26 27 #include <vector> 28 #include <map> 29 #include <set> 30 #include <string> 31 #include <sstream> 32 #include <stack> 33 #include <iostream> 34 #include "tinyxml.h" 35 36 using namespace std; 37 38 39 /* map comparison function */ 40 struct string_less 41 { operatorstring_less42 bool operator()(const std::string& a,const std::string& b) const 43 { 44 return a.compare(b) < 0; 45 } 46 }; 47 48 49 50 /* Data Exceptions */ 51 class DataException : public exception 52 { 53 private: 54 string reason; 55 56 public: DataException(const char * why)57 explicit DataException(const char *why) : reason(why) {} what()58 const char* what() const noexcept override { return reason.c_str(); } string()59 explicit operator string() { return reason; } 60 }; 61 62 63 class DataTypeMismatchException : public DataException 64 { 65 public: DataTypeMismatchException(const char * why)66 explicit DataTypeMismatchException(const char *why) : DataException(why) { } 67 }; 68 69 70 class DataInvalidChildException : public DataException 71 { 72 public: DataInvalidChildException(const char * why)73 explicit DataInvalidChildException(const char *why) : DataException(why) { } 74 }; 75 76 77 class DataElement 78 { 79 public : 80 81 enum class Type { 82 DATA_NULL, 83 DATA_CHAR, 84 DATA_UCHAR, 85 DATA_INT, 86 DATA_UINT, 87 DATA_LONG, 88 DATA_ULONG, 89 DATA_LONGLONG, 90 DATA_FLOAT, 91 DATA_DOUBLE, 92 DATA_STRING, 93 DATA_STR_VECTOR, 94 DATA_CHAR_VECTOR, 95 DATA_UCHAR_VECTOR, 96 DATA_INT_VECTOR, 97 DATA_UINT_VECTOR, 98 DATA_LONG_VECTOR, 99 DATA_ULONG_VECTOR, 100 DATA_LONGLONG_VECTOR, 101 DATA_FLOAT_VECTOR, 102 DATA_DOUBLE_VECTOR, 103 DATA_VOID, 104 DATA_WSTRING 105 }; 106 107 typedef vector<unsigned char> DataElementBuffer; 108 109 typedef vector< DataElementBuffer > DataElementBufferVector; 110 111 private: 112 Type data_type; 113 114 // raw buffer holding data_type element in bytes form. 115 DataElementBuffer data_val; 116 117 //keep the vector of types in a spearate vector of DataElementBuffer. 118 DataElementBufferVector data_val_vector; 119 120 //specializations to extract type: (need to be declared/done OUTSIDE of class scope else "Error: explicit specialization is not allowed in the current scope") 121 //this is apparently fixed in C++17... 122 // so we need to workaround it with a partial specialization using a fake Dummy parameter. 123 124 //if the exact right determineScalarDataType specialization was not used, throw exception at runtime. 125 template<typename U, typename Dummy = int > determineScalarDataType(const U &)126 Type determineScalarDataType(const U& /* type_in */) { throw DataTypeMismatchException("determineScalarDataType(U) usage with unsupported type !"); } 127 128 template< typename Dummy = int > determineScalarDataType(const char &)129 Type determineScalarDataType(const char& /* type_in */) { return DataElement::Type::DATA_CHAR; } 130 131 template< typename Dummy = int > determineScalarDataType(const unsigned char &)132 Type determineScalarDataType(const unsigned char& /* type_in */) { return DataElement::Type::DATA_UCHAR; } 133 134 template< typename Dummy = int > determineScalarDataType(const int &)135 Type determineScalarDataType(const int& /* type_in */) { return DataElement::Type::DATA_INT; } 136 137 template< typename Dummy = int > determineScalarDataType(const unsigned int &)138 Type determineScalarDataType(const unsigned int& /* type_in */) { return DataElement::Type::DATA_UINT; } 139 140 template< typename Dummy = int > determineScalarDataType(const long &)141 Type determineScalarDataType(const long& /* type_in */) { return DataElement::Type::DATA_LONG; } 142 143 template< typename Dummy = int > determineScalarDataType(const unsigned long &)144 Type determineScalarDataType(const unsigned long& /* type_in */) { return DataElement::Type::DATA_ULONG; } 145 146 template< typename Dummy = int > determineScalarDataType(const long long &)147 Type determineScalarDataType(const long long& /* type_in */) { return DataElement::Type::DATA_LONGLONG; } 148 149 template< typename Dummy = int > determineScalarDataType(const float &)150 Type determineScalarDataType(const float& /* type_in */) { return DataElement::Type::DATA_FLOAT; } 151 152 template< typename Dummy = int > determineScalarDataType(const double &)153 Type determineScalarDataType(const double& /* type_in */) { return DataElement::Type::DATA_DOUBLE; } 154 155 //vector versions: 156 //if the exact right determineVectorDataType specialization was not used, throw exception at runtime. 157 template<typename V, typename Dummy = int > determineVectorDataType(const vector<V> &)158 Type determineVectorDataType(const vector<V>& /* type_in */) { throw DataTypeMismatchException("determineVectorDataType(V) usage with unsupported type !"); } 159 160 template< typename Dummy = int > determineVectorDataType(const vector<char> &)161 Type determineVectorDataType(const vector<char>& /* type_in */) { return DataElement::Type::DATA_CHAR_VECTOR; } 162 163 template< typename Dummy = int > determineVectorDataType(const vector<unsigned char> &)164 Type determineVectorDataType(const vector<unsigned char>& /* type_in */) { return DataElement::Type::DATA_UCHAR_VECTOR; } 165 166 template< typename Dummy = int > determineVectorDataType(const vector<int> &)167 Type determineVectorDataType(const vector<int>& /* type_in */) { return DataElement::Type::DATA_INT_VECTOR; } 168 169 template< typename Dummy = int > determineVectorDataType(const vector<unsigned int> &)170 Type determineVectorDataType(const vector<unsigned int>& /* type_in */) { return DataElement::Type::DATA_UINT_VECTOR; } 171 172 template< typename Dummy = int > determineVectorDataType(const vector<long> &)173 Type determineVectorDataType(const vector<long>& /* type_in */) { return DataElement::Type::DATA_LONG_VECTOR; } 174 175 template< typename Dummy = int > determineVectorDataType(const vector<unsigned long> &)176 Type determineVectorDataType(const vector<unsigned long>& /* type_in */) { return DataElement::Type::DATA_ULONG_VECTOR; } 177 178 template< typename Dummy = int > determineVectorDataType(const vector<long long> &)179 Type determineVectorDataType(const vector<long long>& /* type_in */) { return DataElement::Type::DATA_LONGLONG_VECTOR; } 180 181 template< typename Dummy = int > determineVectorDataType(const vector<float> &)182 Type determineVectorDataType(const vector<float>& /* type_in */) { return DataElement::Type::DATA_FLOAT_VECTOR; } 183 184 template< typename Dummy = int > determineVectorDataType(const vector<double> &)185 Type determineVectorDataType(const vector<double>& /* type_in */) { return DataElement::Type::DATA_DOUBLE_VECTOR; } 186 187 public: 188 189 DataElement(); 190 DataElement(DataElement &cloneFrom); 191 ~DataElement(); 192 193 Type getDataType(); 194 char *getDataPointer(); 195 size_t getDataSize(); 196 197 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 198 //set overloads : 199 200 // general templates : for scalars 201 template<typename T, typename Dummy = int > set(const T & scalar_in)202 void set(const T& scalar_in) { 203 204 data_type = determineScalarDataType<T>(scalar_in); 205 206 int unit_size = sizeof(T); 207 //copy in a temporary variable (needed ?) 208 T local_copy = scalar_in; 209 auto* local_copy_ptr = reinterpret_cast<unsigned char*>(&local_copy); 210 211 data_val.assign(local_copy_ptr, local_copy_ptr + unit_size); 212 } 213 214 // general templates : for vector of scalars 215 template<typename T, typename Dummy = int > set(const vector<T> & scalar_vector_in)216 void set(const vector<T>& scalar_vector_in) { 217 218 data_type = determineVectorDataType<T>(scalar_vector_in); 219 220 int unit_size = sizeof(T); 221 222 data_val_vector.clear(); 223 224 DataElementBuffer single_buffer; 225 226 for (auto single_element : scalar_vector_in) { 227 228 //copy in a temporary variable (needed ?) 229 T local_copy = single_element; 230 auto* local_copy_ptr = reinterpret_cast<unsigned char*>(&local_copy); 231 232 single_buffer.assign(local_copy_ptr, local_copy_ptr + unit_size); 233 234 data_val_vector.push_back(single_buffer); 235 } 236 } 237 238 //template specialization : for string 239 template< typename Dummy = int > set(const string & str_in)240 void set(const string& str_in) { 241 242 data_type = DataElement::Type::DATA_STRING; 243 244 data_val.assign(str_in.begin(), str_in.end()); 245 } 246 247 //template specialization : for wstring 248 template< typename Dummy = int > set(const wstring & wstr_in)249 void set(const wstring& wstr_in) { 250 251 data_type = DataElement::Type::DATA_WSTRING; 252 253 //wchar_t is tricky, the terminating zero is actually a (wchar_t)0 ! 254 //wchar_t is typically 16 bits on windows, and 32 bits on Unix, so use sizeof(wchar_t) everywhere. 255 size_t maxLenBytes = (wstr_in.length() + 1) * sizeof(wchar_t); 256 257 //be paranoid, zero the buffer 258 char *tmp_str = (char *)::calloc(maxLenBytes, sizeof(char)); 259 260 //if something awful happens, the last sizeof(wchar_t) is at least zero... 261 ::wcstombs(tmp_str, wstr_in.c_str(), maxLenBytes - sizeof(wchar_t)); 262 263 data_val.assign(tmp_str, tmp_str + maxLenBytes - sizeof(wchar_t)); 264 265 ::free(tmp_str); 266 } 267 268 //template specialization : for vector<string> 269 template< typename Dummy = int > set(const vector<string> & vector_str_in)270 void set(const vector<string>& vector_str_in) { 271 272 data_type = DataElement::Type::DATA_STR_VECTOR; 273 274 data_val_vector.clear(); 275 276 DataElementBuffer single_buffer; 277 278 for (auto single_element : vector_str_in) { 279 280 single_buffer.assign(single_element.begin(), single_element.end()); 281 282 data_val_vector.push_back(single_buffer); 283 } 284 } 285 286 287 ///specific versions 288 void set(const std::set<string> &strset_in); 289 void set(const char *data_in, long size_in); /* voids, file chunks anyone? */ 290 void set(const char *data_in); /* strings, stops at NULL, returns as string */ 291 292 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 293 /* get overloads */ 294 295 template<typename T, typename Dummy = int > get(T & scalar_out)296 void get(T& scalar_out) { 297 298 if (getDataSize() == 0) { 299 throw DataException("Cannot get() the scalar, DataElement is empty !"); 300 } 301 302 DataElement::Type storageType = getDataType(); 303 304 //TODO: smarter way with templates ? 305 if (storageType == DataElement::Type::DATA_CHAR) { 306 char* storage_ptr = reinterpret_cast<char*>(&data_val[0]); 307 //constructor-like 308 scalar_out = T(*storage_ptr); 309 310 } else if (storageType == DataElement::Type::DATA_UCHAR) { 311 auto* storage_ptr = reinterpret_cast<unsigned char*>(&data_val[0]); 312 //constructor-like 313 scalar_out = T(*storage_ptr); 314 } else if (storageType == DataElement::Type::DATA_INT) { 315 int* storage_ptr = reinterpret_cast<int*>(&data_val[0]); 316 //constructor-like 317 scalar_out = T(*storage_ptr); 318 } else if (storageType == DataElement::Type::DATA_UINT) { 319 auto* storage_ptr = reinterpret_cast<unsigned int*>(&data_val[0]); 320 //constructor-like 321 scalar_out = T(*storage_ptr); 322 } else if (storageType == DataElement::Type::DATA_LONG) { 323 long* storage_ptr = reinterpret_cast<long*>(&data_val[0]); 324 //constructor-like 325 scalar_out = T(*storage_ptr); 326 } else if (storageType == DataElement::Type::DATA_ULONG) { 327 auto* storage_ptr = reinterpret_cast<unsigned long*>(&data_val[0]); 328 //constructor-like 329 scalar_out = T(*storage_ptr); 330 } else if (storageType == DataElement::Type::DATA_LONGLONG) { 331 auto* storage_ptr = reinterpret_cast<long long*>(&data_val[0]); 332 //constructor-like 333 scalar_out = T(*storage_ptr); 334 } else if (storageType == DataElement::Type::DATA_FLOAT) { 335 auto* storage_ptr = reinterpret_cast<float*>(&data_val[0]); 336 //constructor-like 337 scalar_out = T(*storage_ptr); 338 } else if (storageType == DataElement::Type::DATA_DOUBLE) { 339 auto* storage_ptr = reinterpret_cast<double*>(&data_val[0]); 340 //constructor-like 341 scalar_out = T(*storage_ptr); 342 } 343 } 344 345 // general templates : for vector of scalars 346 template<typename T, typename Dummy = int > get(vector<T> & scalar_vector_out)347 void get(vector<T>& scalar_vector_out) { 348 349 scalar_vector_out.clear(); 350 351 DataElementBuffer single_buffer; 352 353 Type storageType = getDataType(); 354 355 for (auto single_storage_element : data_val_vector) { 356 357 if (single_storage_element.empty()) { 358 throw DataException("Cannot get(vector<scalar>) on single element because it is empty!"); 359 } 360 361 T scalar_out; 362 363 //TODO: smarter way with templates ? 364 if (storageType == DataElement::Type::DATA_CHAR_VECTOR) { 365 char* storage_ptr = reinterpret_cast<char*>(&single_storage_element[0]); 366 //constructor-like 367 scalar_out = T(*storage_ptr); 368 369 } else if (storageType == DataElement::Type::DATA_UCHAR_VECTOR) { 370 auto* storage_ptr = reinterpret_cast<unsigned char*>(&single_storage_element[0]); 371 //constructor-like 372 scalar_out = T(*storage_ptr); 373 } else if (storageType == DataElement::Type::DATA_INT_VECTOR) { 374 int* storage_ptr = reinterpret_cast<int*>(&single_storage_element[0]); 375 //constructor-like 376 scalar_out = T(*storage_ptr); 377 } else if (storageType == DataElement::Type::DATA_UINT_VECTOR) { 378 auto* storage_ptr = reinterpret_cast<unsigned int*>(&single_storage_element[0]); 379 //constructor-like 380 scalar_out = T(*storage_ptr); 381 } else if (storageType == DataElement::Type::DATA_LONG_VECTOR) { 382 long* storage_ptr = reinterpret_cast<long*>(&single_storage_element[0]); 383 //constructor-like 384 scalar_out = T(*storage_ptr); 385 } else if (storageType == DataElement::Type::DATA_ULONG_VECTOR) { 386 auto* storage_ptr = reinterpret_cast<unsigned long*>(&single_storage_element[0]); 387 //constructor-like 388 scalar_out = T(*storage_ptr); 389 } else if (storageType == DataElement::Type::DATA_LONGLONG_VECTOR) { 390 auto* storage_ptr = reinterpret_cast<long long*>(&single_storage_element[0]); 391 //constructor-like 392 scalar_out = T(*storage_ptr); 393 } else if (storageType == DataElement::Type::DATA_FLOAT_VECTOR) { 394 auto* storage_ptr = reinterpret_cast<float*>(&single_storage_element[0]); 395 //constructor-like 396 scalar_out = T(*storage_ptr); 397 } else if (storageType == DataElement::Type::DATA_DOUBLE_VECTOR) { 398 auto* storage_ptr = reinterpret_cast<double*>(&single_storage_element[0]); 399 //constructor-like 400 scalar_out = T(*storage_ptr); 401 } 402 403 scalar_vector_out.push_back(scalar_out); 404 } //end for. 405 } 406 407 //template specialization : for string or void* returned as string 408 template< typename Dummy = int > get(string & str_out)409 void get(string& str_out) { 410 411 //reset 412 str_out.clear(); 413 414 if (data_type == DataElement::Type::DATA_NULL) { 415 //it means TinyXML has parsed an empty tag, 416 //so return an empty string. 417 return; 418 } 419 420 if (data_type != DataElement::Type::DATA_STRING && data_type != DataElement::Type::DATA_VOID) { 421 throw(DataTypeMismatchException("Type mismatch, neither a STRING nor a VOID*")); 422 } 423 424 for (auto single_char : data_val) { 425 str_out.push_back((char)single_char); 426 } 427 } 428 429 //template specialization : for wstring 430 template< typename Dummy = int > get(wstring & wstr_out)431 void get(wstring& wstr_out) { 432 433 //reset 434 wstr_out.clear(); 435 436 if (data_type == DataElement::Type::DATA_NULL) { 437 //it means TinyXML has parsed an empty tag, 438 //so return an empty string. 439 return; 440 } 441 442 if (data_type != DataElement::Type::DATA_WSTRING) { 443 throw(DataTypeMismatchException("Type mismatch, not a WSTRING")); 444 } 445 446 if (getDataSize() >= sizeof(wchar_t)) { 447 448 //data_val is an array of bytes holding wchar_t characters, plus a terminating (wchar_t)0 449 //wchar_t is typically 16 bits on windows, and 32 bits on Unix, so use sizeof(wchar_t) everywhere. 450 size_t maxNbWchars = getDataSize() / sizeof(wchar_t); 451 452 //be paranoid, zero the buffer 453 auto *tmp_wstr = (wchar_t *)::calloc(maxNbWchars + 1, sizeof(wchar_t)); 454 455 //the last wchar_t is actually zero if anything goes wrong... 456 ::mbstowcs(tmp_wstr, (const char*)&data_val[0], maxNbWchars); 457 458 wstr_out.assign(tmp_wstr); 459 460 ::free(tmp_wstr); 461 } 462 } 463 464 //template specialization : for vector<string> 465 template< typename Dummy = int > get(vector<string> & vector_str_out)466 void get(vector<string>& vector_str_out) { 467 468 if (data_type != DataElement::Type::DATA_STR_VECTOR) { 469 throw(DataTypeMismatchException("Type mismatch, not a STRING VECTOR")); 470 } 471 472 vector_str_out.clear(); 473 474 string single_buffer; 475 476 for (auto single_element : data_val_vector) { 477 478 single_buffer.assign(single_element.begin(), single_element.end()); 479 480 vector_str_out.push_back(single_buffer); 481 } 482 } 483 484 //special versions: 485 void get(DataElementBuffer& data_out); /* getting a void or string */ 486 void get(std::set<string> &strset_out); 487 488 489 /* special get functions, saves creating unnecessary vars */ getChar()490 int getChar() { char i_get; get(i_get); return i_get; }; getUChar()491 unsigned int getUChar() { unsigned char i_get; get(i_get); return i_get; }; getInt()492 int getInt() { int i_get; get(i_get); return i_get; }; getUInt()493 unsigned int getUInt() { unsigned int i_get; get(i_get); return i_get; }; getLong()494 long getLong() { long l_get; get(l_get); return l_get; }; getULong()495 unsigned long getULong() { unsigned long l_get; get(l_get); return l_get; }; getLongLong()496 long long getLongLong() { long long l_get; get(l_get); return l_get; }; getFloat()497 float getFloat() { float f_get; get(f_get); return f_get; }; getDouble()498 double getDouble() { double d_get; get(d_get); return d_get; }; 499 500 std::string toString(); 501 }; 502 503 /// 504 class DataNode 505 { 506 private: 507 DataNode *parentNode; 508 vector<DataNode *> children; 509 map<string, vector<DataNode *>, string_less> childmap; 510 map<string, unsigned int, string_less> childmap_ptr; 511 512 string node_name; 513 DataElement *data_elem; 514 unsigned int ptr; 515 516 517 public: 518 DataNode(); 519 explicit DataNode(const char *name_in); 520 DataNode(const char *name_in, DataElement &cloneFrom); 521 DataNode(const char *name_in, DataNode &cloneFrom); 522 523 ~DataNode(); 524 525 void setName(const char *name_in); getName()526 string &getName() { return node_name; } 527 getParentNode()528 DataNode *getParentNode() { return parentNode; }; setParentNode(DataNode & parentNode_in)529 void setParentNode(DataNode &parentNode_in) { parentNode = &parentNode_in; }; 530 531 size_t numChildren(); /* Number of children */ 532 size_t numChildren(const char *name_in); /* Number of children named 'name_in' */ 533 534 DataElement *element(); /* DataElement at this node */ 535 536 DataNode *newChild(const char *name_in); 537 DataNode *newChild(const char *name_in, DataNode *otherNode); 538 DataNode *newChildCloneFrom(const char *name_in, DataNode *cloneFrom); 539 DataNode *child(const char *name_in, int index = 0); 540 DataNode *child(int index); 541 542 543 bool hasAnother(const char *name_in); /* useful for while() loops in conjunction with getNext() */ 544 bool hasAnother(); 545 DataNode *getNext(const char *name_in); /* get next of specified name */ 546 DataNode *getNext(); /* get next child */ 547 void rewind(const char *name_in); /* rewind specific */ 548 void rewind(); /* rewind generic */ 549 void rewindAll(); 550 551 void findAll(const char *name_in, vector<DataNode *> &node_list_out); 552 string()553 explicit operator string () { string s; element()->get(s); return s; } 554 explicit operator const char * () { if (element()->getDataType() == DataElement::Type::DATA_STRING) { return element()->getDataPointer(); } else { return nullptr; } } 555 explicit operator char () { char v=0; element()->get(v); return v; } 556 explicit operator unsigned char () { unsigned char v=0; element()->get(v); return v; } 557 explicit operator int () { int v=0; element()->get(v); return v; } 558 explicit operator unsigned int () { unsigned int v=0; element()->get(v); return v; } 559 explicit operator long () { long v=0; element()->get(v); return v; } 560 explicit operator unsigned long () { unsigned long v=0; element()->get(v); return v; } 561 explicit operator long long () { long long v=0; element()->get(v); return v; } 562 explicit operator float () { float v=0; element()->get(v); return v; } 563 explicit operator double () { double v=0; element()->get(v); return v; } 564 565 explicit operator vector<char> () { vector<char> v; element()->get(v); return v; } 566 explicit operator vector<unsigned char> () { vector<unsigned char> v; element()->get(v); return v; } 567 explicit operator vector<int> () { vector<int> v; element()->get(v); return v; } 568 explicit operator vector<unsigned int> () { vector<unsigned int> v; element()->get(v); return v; } 569 explicit operator vector<long> () { vector<long> v; element()->get(v); return v; } 570 explicit operator vector<unsigned long> () { vector<unsigned long> v; element()->get(v); return v; } 571 explicit operator vector<float> () { vector<float> v; element()->get(v); return v; } 572 explicit operator vector<double> () { vector<double> v; element()->get(v); return v; } 573 574 const string &operator= (const string &s) { element()->set(s); return s; } 575 const wstring &operator= (const wstring &s) { element()->set(s); return s; } 576 577 char operator= (char i) { element()->set(i); return i; } 578 unsigned char operator= (unsigned char i) { element()->set(i); return i; } 579 int operator= (int i) { element()->set(i); return i; } 580 unsigned int operator= (unsigned int i) { element()->set(i); return i; } 581 long operator= (long i) { element()->set(i); return i; } 582 unsigned long operator= (unsigned long i) { element()->set(i); return i; } 583 long long operator= (long long i) { element()->set(i); return i; } 584 float operator= (float i) { element()->set(i); return i; } 585 double operator= (double i) { element()->set(i); return i; } 586 587 vector<char> &operator= (vector<char> &v) { element()->set(v); return v; } 588 vector<unsigned char> &operator= (vector<unsigned char> &v) { element()->set(v); return v; } 589 vector<int> &operator= (vector<int> &v) { element()->set(v); return v; } 590 vector<unsigned int> &operator= (vector<unsigned int> &v) { element()->set(v); return v; } 591 vector<long> &operator= (vector<long> &v) { element()->set(v); return v; } 592 vector<unsigned long> &operator= (vector<unsigned long> &v) { element()->set(v); return v; } 593 vector<float> &operator= (vector<float> &v) { element()->set(v); return v; } 594 vector<double> &operator= (vector<double> &v) { element()->set(v); return v; } 595 596 DataNode *operator[] (const char *name_in) { return getNext(name_in); } 597 DataNode *operator[] (int idx) { return child(idx); } 598 operator()599 bool operator() (const char *name_in) { return hasAnother(name_in); } operator()600 bool operator() () { return hasAnother(); } 601 602 DataNode *operator ^(const char *name_in) { return newChild(name_in); } 603 }; 604 605 606 typedef vector<DataNode *> DataNodeList; 607 608 enum DT_FloatingPointPolicy { 609 USE_FLOAT, 610 USE_DOUBLE 611 }; 612 613 class DataTree 614 { 615 private: 616 DataNode dn_root; 617 618 string wsEncode(const wstring& wstr); 619 wstring wsDecode(const string& str); 620 621 public: 622 explicit DataTree(const char *name_in); 623 DataTree(); 624 ~DataTree(); 625 626 DataNode *rootNode(); 627 628 void nodeToXML(DataNode *elem, TiXmlElement *elxml); 629 void setFromXML(DataNode *elem, TiXmlNode *elxml, bool root_node=true, DT_FloatingPointPolicy fpp=USE_FLOAT); 630 void decodeXMLText(DataNode *elem, const char *in_text, DT_FloatingPointPolicy fpp); 631 632 void printXML(); /* print datatree as XML */ 633 634 bool LoadFromFileXML(const std::string& filename, DT_FloatingPointPolicy fpp=USE_FLOAT); 635 bool SaveToFileXML(const std::string& filename); 636 637 }; 638