Warning, /include/Geant4/tools/xml/tree is written in an unsupported language. File is not indexed.
0001 // Copyright (C) 2010, Guy Barrand. All rights reserved.
0002 // See the file tools.license for terms.
0003
0004 #ifndef tools_xml_tree
0005 #define tools_xml_tree
0006
0007 #include "element"
0008
0009 #include "../sout"
0010 #include "../strip"
0011 #include "../S_STRING"
0012 #include "../forit"
0013
0014 #include <list>
0015 #include <ostream>
0016
0017 namespace tools {
0018 namespace xml {
0019
0020 // A tree is :
0021 // <tree atb1="" atb2="" ...>
0022 // ...
0023 // <tree...>
0024 // </tree>
0025 // ...
0026 // <element atb1="" atb2="" ...> value </element>
0027 // ...
0028 // </tree>
0029 //
0030 // tree.attribute_value(<name>,s)
0031 // retrieve the value of atb <name> of a <tag>
0032 // tree.attribute_value(<element>,<name>,s)
0033 // retrieve the value of an atb <name> of a <element> of a <tree>
0034 //
0035
0036 class tree;
0037
0038 class factory {
0039 public:
0040 virtual ~factory(){}
0041 public:
0042 typedef std::pair<std::string,std::string> atb;
0043 public:
0044 virtual tree* create(const std::string& a_tag_name,const std::vector<atb>& a_atbs,tree* a_parent) = 0;
0045 };
0046
0047 class tree : public virtual ielem {
0048 public:
0049 TOOLS_SCLASS(tools::xml::tree)
0050 public:
0051 static cid id_class() {return 1;}
0052 virtual void* cast(cid a_class) const {
0053 if(void* p = cmp_cast<tree>(this,a_class)) {return p;}
0054 else return 0;
0055 }
0056 public:
0057 typedef std::pair<std::string,std::string> atb;
0058 typedef bool (*exec_func)(tree&,void*);
0059 enum copy_what { copy_attributes, copy_elements, copy_children, copy_all };
0060 public:
0061 tree(const std::string& a_tag_name,factory& a_factory,tree* a_parent)
0062 :m_tag_name(a_tag_name)
0063 ,m_factory(a_factory)
0064 ,m_parent(a_parent)
0065 ,m_save(true)
0066 ,m_data_1(0)
0067 ,m_data_2(0)
0068 ,m_data_int(0)
0069 ,m_depth(0)
0070 {
0071 #ifdef TOOLS_MEM
0072 mem::increment(s_class().c_str());
0073 #endif
0074 }
0075
0076 virtual ~tree(){
0077 clear();
0078 #ifdef TOOLS_MEM
0079 mem::decrement(s_class().c_str());
0080 #endif
0081 }
0082
0083 protected:
0084 tree(const tree& a_from)
0085 :ielem(a_from)
0086 ,m_tag_name(a_from.m_tag_name)
0087 ,m_factory(a_from.m_factory)
0088 ,m_parent(0)
0089 ,m_save(0)
0090 ,m_data_1(0)
0091 ,m_data_2(0)
0092 ,m_data_int(0)
0093 ,m_depth(0)
0094 {
0095 #ifdef TOOLS_MEM
0096 mem::increment(s_class().c_str());
0097 #endif
0098 }
0099
0100 tree& operator=(const tree&){return *this;}
0101
0102 public:
0103 virtual bool invalidate() {return true;}
0104
0105 const std::list<ielem*>& childs() const {return m_childs;}
0106
0107 ///////////////////////////////////////////////////////
0108 /// attributes ////////////////////////////////////////
0109 ///////////////////////////////////////////////////////
0110 const std::vector<atb>& attributes() const {return m_atbs;}
0111
0112 void add_attribute(const std::string& a_name,const std::string& a_value){
0113 // No check is done about an existing a_name.
0114 m_atbs.push_back(atb(a_name,a_value));
0115 }
0116
0117 bool is_attribute(const std::string& a_name) const {
0118 size_t number = m_atbs.size();
0119 for(size_t index=0;index<number;index++) {
0120 if(m_atbs[index].first==a_name) return true;
0121 }
0122 return false;
0123 }
0124
0125 void set_attributes(const std::vector<atb>& a_atbs) {
0126 m_atbs = a_atbs;
0127 }
0128 const std::string& tag_name() const {return m_tag_name;}
0129
0130 bool attribute_value(const std::string& a_atb,std::string& a_value) const {
0131 a_value.clear();
0132 size_t linen = m_atbs.size();
0133 for(size_t count=0;count<linen;count++) {
0134 if(m_atbs[count].first==a_atb) {
0135 a_value = m_atbs[count].second;
0136 return true;
0137 }
0138 }
0139 return false;
0140 }
0141
0142 template <class T>
0143 bool attribute_value(const std::string& a_atb,T& a_value) const {
0144 std::string sv;
0145 if(!attribute_value(a_atb,sv)) {a_value=T();return false;}
0146 return to<T>(sv,a_value);
0147 }
0148
0149 void remove_attributes(const std::string& a_atb) {
0150 std::vector<atb>::iterator it;
0151 for(it=m_atbs.begin();it!=m_atbs.end();) {
0152 if((*it).first==a_atb) {
0153 it = m_atbs.erase(it);
0154 } else {
0155 ++it;
0156 }
0157 }
0158 }
0159
0160 bool remove_attribute(const std::string& a_name){
0161 //TOOLS_STL : to be checked :
0162 std::vector<atb>::iterator it = m_atbs.begin();
0163 size_t linen = m_atbs.size();
0164 for(size_t count=0;count<linen;count++,++it) {
0165 if(m_atbs[count].first==a_name) {
0166 m_atbs.erase(it);
0167 return true; //Found and removed.
0168 }
0169 }
0170 return false; //Not found.
0171 }
0172
0173 ///////////////////////////////////////////////////////
0174 /// elements //////////////////////////////////////////
0175 ///////////////////////////////////////////////////////
0176 void add_element(const std::string& a_name,const std::vector<atb>& a_atbs,const std::string& a_value){
0177 m_childs.push_back(new element(a_name,a_atbs,a_value));
0178 }
0179
0180 bool element_value(const std::string& a_name,std::string& a_value) const {
0181 tools_lforcit(ielem*,m_childs,it) {
0182 if(element* _elem = id_cast<ielem,element>(*(*it))) {
0183 if(a_name==_elem->name()) {
0184 a_value = _elem->value();
0185 return true;
0186 }
0187 }
0188 }
0189 a_value.clear();
0190 return false;
0191 }
0192
0193 /*
0194 //NOTE : print is a Python keyword.
0195 void dump(std::ostream& a_out){
0196 a_out << "dump :"
0197 << " -----> " << this << " parent : " << m_parent << std::endl;
0198 a_out << " data1 : " << m_data_1
0199 << " data2 : " << m_data_2
0200 << " dataInt : " << m_data_int
0201 << std::endl;
0202
0203 {size_t atbn = m_atbs.size();
0204 for(size_t index=0;index<atbn;index++) {
0205 a_out << " attribute : " << sout(m_atbs[index].first) << " "
0206 << sout(m_atbs[index].second) << std::endl;
0207 }}
0208
0209 {tools_lforit(element*,m_elems,it) {
0210 a_out << " element : \"" << (*it)->name() << "\" \""
0211 << (*it)->value() << "\"" << std::endl;
0212 }}
0213
0214 {tools_lforit(tree*,m_children,it) {
0215 (*it)->dump(a_out);
0216 }}
0217 }
0218
0219 const std::list<element*>& elements() const {return m_elems;}
0220
0221 */
0222
0223 bool element_atb_value(const std::string& a_elem,const std::string& a_atb,std::string& a_value) const {
0224 a_value.clear();
0225 tools_lforcit(ielem*,m_childs,it) {
0226 if(element* _elem = id_cast<ielem,element>(*(*it))) {
0227 if(a_elem==_elem->name()) {
0228 if(_elem->attribute_value(a_atb,a_value)) return true;
0229 }
0230 }
0231 }
0232 return false;
0233 }
0234
0235 template <class T>
0236 bool element_atb_value(const std::string& a_elem,const std::string& a_atb,T& a_value) const {
0237 std::string sv;
0238 if(!element_atb_value(a_elem,a_atb,sv)) {a_value=T();return false;}
0239 return to<T>(sv,a_value);
0240 }
0241
0242 //////////////////////////////////////////////////
0243 /// for osc //////////////////////////////////////
0244 //////////////////////////////////////////////////
0245 bool is_element(const std::string& a_name) const {
0246 tools_lforcit(ielem*,m_childs,it) {
0247 if(element* _elem = id_cast<ielem,element>(*(*it))) {
0248 if(a_name==_elem->name()) return true;
0249 }
0250 }
0251 return false;
0252 }
0253
0254 bool set_element_value(const std::string& a_name,const std::string& a_value,int a_index = 0){
0255 int index = 0;
0256 tools_lforcit(ielem*,m_childs,it) {
0257 if(element* _elem = id_cast<ielem,element>(*(*it))) {
0258 if(a_name==_elem->name()) {
0259 if(index==a_index) {
0260 _elem->set_value(a_value);
0261 return true;
0262 } else {
0263 index ++;
0264 }
0265 }
0266 }
0267 }
0268 // Not found, add one :
0269 std::vector<atb> atts;
0270 add_element(a_name,atts,a_value);
0271 return true;
0272 }
0273
0274 bool set_attribute_value(const std::string& a_atb,const std::string& a_value) {
0275 tools_vforit(atb,m_atbs,it) {
0276 if((*it).first==a_atb) {
0277 (*it).second = a_value;
0278 return true;
0279 }
0280 }
0281 // Not found, add one :
0282 m_atbs.push_back(atb(a_atb,a_value));
0283 return true;
0284 }
0285
0286 bool has_empty_attribute_value(std::ostream& a_out) const{
0287 empty_visitor visitor(a_out);
0288 visitor.m_status = true;
0289 const_cast<tree*>(this)->post_execute(check_item,&visitor);
0290 return visitor.m_status;
0291 }
0292
0293 class empty_visitor {
0294 public:
0295 empty_visitor(std::ostream& a_out)
0296 :f_out(a_out),m_status(true){}
0297 public:
0298 std::ostream& f_out;
0299 bool m_status;
0300 };
0301
0302 void post_execute(exec_func a_function,void* a_tag) {
0303 if(!a_function) return;
0304
0305 if(!a_function(*this,a_tag)) return;
0306
0307 tools_lforcit(ielem*,m_childs,it) {
0308 if(tree* _tree = id_cast<ielem,tree>(*(*it))) {
0309 _tree->post_execute(a_function,a_tag);
0310 }
0311 }
0312 }
0313
0314 static bool check_item(tree& a_tree,void* a_tag){
0315 empty_visitor* visitor = (empty_visitor*)a_tag;
0316
0317 {const std::vector<atb>& atbs = a_tree.attributes();
0318 size_t atbn = atbs.size();
0319 for(size_t index=0;index<atbn;index++) {
0320 const std::string& _atb = atbs[index].first;
0321 const std::string& atbv = atbs[index].second;
0322 if(atbv.empty()) {
0323 visitor->f_out << "check_item :"
0324 << " for XML item " << sout(a_tree.tag_name())
0325 << ", attribute " << sout(_atb) << " has an empty value."
0326 << std::endl;
0327 visitor->m_status = false;
0328 }
0329 }}
0330
0331 {tools_lforcit(ielem*,a_tree.m_childs,it) {
0332 if(element* _elem = id_cast<ielem,element>(*(*it))) {
0333 const std::vector<atb>& atbs = _elem->attributes();
0334 size_t atbn = atbs.size();
0335 for(size_t index=0;index<atbn;index++) {
0336 const std::string& _atb = atbs[index].first;
0337 const std::string& atbv = atbs[index].second;
0338 if(atbv.empty()) {
0339 visitor->f_out << "ItemM::check_item :"
0340 << " for XML item " << sout(a_tree.tag_name())
0341 << ", attribute " << sout(_atb) << " has an empty value."
0342 << std::endl;
0343 visitor->m_status = false;
0344 }
0345 }
0346 }}}
0347
0348 return true;
0349 }
0350
0351 static void collect_by_tag(tree& a_tree,const std::string& a_tag,std::vector<tree*>& a_items) {
0352 if(a_tree.tag_name()==a_tag) a_items.push_back(&a_tree);
0353 tools_lforcit(ielem*,a_tree.m_childs,it) {
0354 if(tree* _tree = id_cast<ielem,tree>(*(*it))) {
0355 collect_by_tag(*_tree,a_tag,a_items);
0356 }
0357 }
0358 }
0359
0360 tree* find_by_tag(const std::string& a_tag) const {
0361 if(tag_name()==a_tag) return const_cast<tree*>(this);
0362 // Look children :
0363 tools_lforcit(ielem*,m_childs,it) {
0364 if(tree* _tree = id_cast<ielem,tree>(*(*it))) {
0365 tree* itemML = _tree->find_by_tag(a_tag);
0366 if(itemML) return itemML;
0367 }}
0368 return 0;
0369 }
0370
0371 static void unique(std::vector<tree*>& a_items) {
0372 std::vector<tree*> items2;
0373
0374 tools_vforcit(tree*,a_items,it) {
0375 std::string name;
0376 if(!(*it)->attribute_value("name",name)) continue;
0377 if(name.empty()) continue;
0378
0379 bool found = false;
0380 {tools_vforit(tree*,items2,it2) {
0381 std::string name2;
0382 (*it2)->attribute_value("name",name2);
0383 if(name2==name) {
0384 found = true;
0385 break;
0386 }
0387 }}
0388 if(!found) {
0389 items2.push_back(*it);
0390 }
0391 }
0392
0393 a_items = items2;
0394 }
0395
0396 tree* find_item(const std::string& a_name) const {
0397 {size_t linen = m_atbs.size();
0398 for(unsigned int count=0;count<linen;count++) {
0399 if(m_atbs[count].first=="name") {
0400 if(m_atbs[count].second==a_name) return const_cast<tree*>(this);
0401 break;
0402 }
0403 }}
0404
0405 // Look children :
0406 tools_lforcit(ielem*,m_childs,it) {
0407 if(tree* _tree = id_cast<ielem,tree>(*(*it))) {
0408 tree* item = _tree->find_item(a_name);
0409 if(item) return item;
0410 }}
0411 return 0;
0412 }
0413
0414 tree* find_item_with_tag(const std::string& a_tag,
0415 const std::string& a_name) const {
0416 if(a_tag==tag_name()) {
0417 std::string _s;
0418 attribute_value("name",_s);
0419 if(a_name==_s) return const_cast<tree*>(this);
0420 }
0421
0422 // Look children :
0423 tools_lforcit(ielem*,m_childs,it) {
0424 if(tree* _tree = id_cast<ielem,tree>(*(*it))) {
0425 tree* item = _tree->find_item_with_tag(a_tag,a_name);
0426 if(item) return item;
0427 }}
0428 return 0;
0429 }
0430
0431 void remove_elements(const std::string& a_name){
0432 // TOOLS_STL : to be checked :
0433 std::list<ielem*>::iterator it;
0434 for(it=m_childs.begin();it!=m_childs.end();) {
0435 if(element* _elem = id_cast<ielem,element>(*(*it))) {
0436 if(a_name==_elem->name()) {
0437 it = m_childs.erase(it);
0438 delete _elem;
0439 } else {
0440 ++it;
0441 }
0442 } else {
0443 ++it;
0444 }
0445 }
0446 }
0447
0448 void add_child(tree* a_tree) {m_childs.push_back(a_tree);}
0449
0450 tree* create_copy(tree* a_parent) {
0451 tree* itemML = m_factory.create(m_tag_name,m_atbs,a_parent);
0452 if(!itemML) return 0;
0453 itemML->m_atbs = m_atbs;
0454 //FIXME : m_save
0455
0456 {tools_lforcit(ielem*,m_childs,it) {
0457 if(element* _elem = id_cast<ielem,element>(*(*it))) {
0458 itemML->m_childs.push_back(new element(*_elem));
0459 }}}
0460
0461 {tools_lforcit(ielem*,m_childs,it) {
0462 if(tree* _tree = id_cast<ielem,tree>(*(*it))) {
0463 //FIXME : could we have mismatch parent/child ?
0464 tree* obj = _tree->create_copy(itemML);
0465 if(!obj) {
0466 delete itemML;
0467 return 0;
0468 }
0469 itemML->add_child(obj);
0470 }}}
0471
0472 return itemML;
0473 }
0474
0475 bool copy(const tree& a_from,
0476 copy_what a_what = copy_all,
0477 bool a_clear = true){
0478
0479 // Copy data (atbs, propertis, children) of a_from onto this.
0480 if((a_what==copy_all)||(a_what==copy_attributes)) {
0481 if(a_clear) m_atbs.clear();
0482 tools_vforcit(atb,a_from.m_atbs,it) m_atbs.push_back(*it);
0483 }
0484
0485 if((a_what==copy_all)||(a_what==copy_elements)) {
0486 if(a_clear) delete_sub_elems();
0487 tools_lforcit(ielem*,a_from.m_childs,it) {
0488 if(element* _elem = id_cast<ielem,element>(*(*it))) {
0489 m_childs.push_back(new element(*_elem));
0490 }
0491 }
0492 }
0493
0494 if((a_what==copy_all)||(a_what==copy_children)) {
0495 if(a_clear) delete_sub_trees();
0496 tools_lforcit(ielem*,a_from.m_childs,it) {
0497 if(tree* _tree = id_cast<ielem,tree>(*(*it))) {
0498 //FIXME : could we have mismatch parent/child ?
0499 tree* obj = _tree->create_copy(this);
0500 if(!obj) {
0501 // Something wrong, cleanup this.
0502 clear();
0503 return false;
0504 }
0505 add_child(obj);
0506 }
0507 }
0508 }
0509
0510 //FIXME : m_save
0511
0512 return true;
0513 }
0514
0515
0516 void replace(const std::string& a_old,const std::string& a_new) {
0517 // Used by the obuild template system.
0518 {size_t atbn = m_atbs.size();
0519 for(size_t index=0;index<atbn;index++) {
0520 std::string& value = m_atbs[index].second;
0521 replace_(value,a_old,a_new);
0522 }}
0523
0524 tools_lforit(ielem*,m_childs,it) {
0525 if(tree* _tree = id_cast<ielem,tree>(*(*it))) {
0526 _tree->replace(a_old,a_new);
0527 } else if(element* _elem = id_cast<ielem,element>(*(*it))) {
0528 _elem->replace(a_old,a_new);
0529 }
0530 }
0531 }
0532
0533 static void collect_by_attribute(tree& a_tree,
0534 const std::string& a_tag,
0535 std::vector<tree*>& a_items) {
0536 std::string value;
0537 if(a_tree.attribute_value(a_tag,value)) a_items.push_back(&a_tree);
0538 tools_lforcit(ielem*,a_tree.m_childs,it) {
0539 if(tree* _tree = id_cast<ielem,tree>(*(*it))) {
0540 collect_by_attribute(*_tree,a_tag,a_items);
0541 }
0542 }
0543 }
0544
0545 bool element_values(const std::string& a_name,
0546 std::vector<std::string>& a_values) const {
0547 a_values.clear();
0548 tools_lforcit(ielem*,m_childs,it) {
0549 if(element* _elem = id_cast<ielem,element>(*(*it))) {
0550 if(a_name==_elem->name()) {
0551 a_values.push_back(_elem->value());
0552 }
0553 }
0554 }
0555 return true;
0556 }
0557
0558 void post_execute_backward(exec_func a_function,void* a_tag){
0559 if(!a_function) return;
0560 tools_lforcit(ielem*,m_childs,it) {
0561 if(tree* _tree = id_cast<ielem,tree>(*(*it))) {
0562 _tree->post_execute_backward(a_function,a_tag);
0563 }
0564 }
0565 if(!a_function(*this,a_tag)) return;
0566 }
0567
0568 tree* find_by_attribute(const std::string& a_atb,const std::string& a_value,
0569 bool a_up_down = true,bool a_left_right = true) const {
0570 if(a_up_down) {
0571 std::string _s;
0572 attribute_value(a_atb,_s);
0573 if(_s==a_value) return const_cast<tree*>(this);
0574
0575 if(a_left_right) {
0576 tools_lforcit(ielem*,m_childs,it) {
0577 if(tree* _tree = id_cast<ielem,tree>(*(*it))) {
0578 tree* itemML =
0579 _tree->find_by_attribute(a_atb,a_value,a_up_down,a_left_right);
0580 if(itemML) return itemML;
0581 }
0582 }
0583 } else {
0584 std::list<ielem*>::const_reverse_iterator it;
0585 for(it=m_childs.rbegin();it!=m_childs.rend();++it) {
0586 if(tree* _tree = id_cast<ielem,tree>(*(*it))) {
0587 tree* itemML =
0588 _tree->find_by_attribute(a_atb,a_value,a_up_down,a_left_right);
0589 if(itemML) return itemML;
0590 }}
0591 }
0592 } else {
0593 if(a_left_right) {
0594 tools_lforcit(ielem*,m_childs,it) {
0595 if(tree* _tree = id_cast<ielem,tree>(*(*it))) {
0596 tree* itemML =
0597 _tree->find_by_attribute(a_atb,a_value,a_up_down,a_left_right);
0598 if(itemML) return itemML;
0599 }}
0600 } else {
0601 std::list<ielem*>::const_reverse_iterator it;
0602 for(it=m_childs.rbegin();it!=m_childs.rend();++it) {
0603 if(tree* _tree = id_cast<ielem,tree>(*(*it))) {
0604 tree* itemML =
0605 _tree->find_by_attribute(a_atb,a_value,a_up_down,a_left_right);
0606 if(itemML) return itemML;
0607 }}
0608 }
0609
0610 std::string _s;
0611 attribute_value(a_atb,_s);
0612 if(_s==a_value) return const_cast<tree*>(this);
0613
0614 }
0615 return 0;
0616 }
0617
0618 void dump_xml(std::ostream& a_out,const std::string& a_spaces = "") {
0619
0620 // begin tag :
0621 a_out << a_spaces << "<" << m_tag_name;
0622 {size_t atbn = m_atbs.size();
0623 for(size_t index=0;index<atbn;index++) {
0624 a_out << " " << m_atbs[index].first << "="
0625 << sout(m_atbs[index].second);
0626 }}
0627 a_out << ">" << std::endl;
0628
0629 {tools_lforcit(ielem*,m_childs,it) {
0630 if(element* _elem = id_cast<ielem,element>(*(*it))) {
0631
0632 const std::vector<atb>& atbs = _elem->attributes();
0633
0634 bool isCallback = false;
0635
0636 a_out << a_spaces << " <" << _elem->name();
0637 size_t atbn = atbs.size();
0638 for(size_t index=0;index<atbn;index++) {
0639 a_out << " " << atbs[index].first << "="
0640 << sout(atbs[index].second);
0641 if(atbs[index].first=="exec") isCallback = true;
0642 }
0643 if(_elem->value().empty()) {
0644 a_out << "/>" << std::endl;
0645 } else {
0646 a_out << ">";
0647 std::string value = to_xml(_elem->value());
0648 if(isCallback) {
0649 if(value.find("\\n\\")==std::string::npos) {
0650 a_out << value;
0651 } else {
0652 a_out << std::endl;
0653 replace_(value,"\\n\\","@OnX@");
0654 replace_(value,"@OnX@","\\n\\\n");
0655 strip(value,trailing,' ');
0656 a_out << value;
0657 size_t l = value.size();
0658 if(l && value[l-1]!='\n') a_out << std::endl;
0659 a_out << a_spaces << " ";
0660 }
0661 } else {
0662 a_out << value;
0663 }
0664 a_out << "</" << _elem->name() << ">" << std::endl;
0665 }
0666 }}}
0667
0668 // End tag :
0669 a_out << a_spaces << "</" << m_tag_name << ">" << std::endl;
0670 }
0671
0672 bool set_element_atb_value(const std::string& a_elem,
0673 const std::string& a_atb,
0674 const std::string& a_value,int a_index = 0){
0675 if(a_elem.empty()) {
0676 size_t linen = m_atbs.size();
0677 for(size_t count=0;count<linen;count++) {
0678 if(m_atbs[count].first==a_atb) {
0679 m_atbs[count].second = a_value;
0680 return true;
0681 }
0682 }
0683 // Not found, add it :
0684 m_atbs.push_back(atb(a_atb,a_value));
0685 return true;
0686 } else {
0687 int index = 0;
0688 tools_lforcit(ielem*,m_childs,it) {
0689 if(element* _elem = id_cast<ielem,element>(*(*it))) {
0690 if(a_elem==_elem->name()) {
0691 if(index==a_index) {
0692 _elem->set_attribute_value(a_atb,a_value);
0693 return true;
0694 } else {
0695 index++;
0696 }
0697 }
0698 }}
0699 return false;
0700 }
0701 }
0702
0703 // NOTE : used in osc. Should be removed.
0704 void sub_trees(std::list<tree*>& a_list) const {
0705 a_list.clear();
0706 tools_lforcit(ielem*,m_childs,it) {
0707 if(tree* _tree = id_cast<ielem,tree>(*(*it))) {
0708 a_list.push_back(_tree);
0709 }}
0710 }
0711 void sub_elems(std::list<element*>& a_list) const {
0712 a_list.clear();
0713 tools_lforcit(ielem*,m_childs,it) {
0714 if(element* _elem = id_cast<ielem,element>(*(*it))) {
0715 a_list.push_back(_elem);
0716 }}
0717 }
0718
0719 bool replace_child(tree* a_old,tree* a_new) {
0720 tools_lforit(ielem*,m_childs,it) {
0721 if(tree* _tree = id_cast<ielem,tree>(*(*it))) {
0722 if(_tree==a_old) {
0723 (*it) = a_new;
0724 return true; //replacement done.
0725 }
0726 }}
0727 return false; //no replacement done.
0728 }
0729
0730 // used in OnX/Widget.
0731 virtual void* cast(const std::string& a_class) const {
0732 if(void* p = cmp_cast<tree>(this,a_class)) {return p;}
0733 else return 0;
0734 }
0735
0736 void delete_element(const std::string& a_name) {
0737 tools_lforit(ielem*,m_childs,it) {
0738 if(element* _elem = id_cast<ielem,element>(*(*it))) {
0739 if(a_name==_elem->name()) {
0740 m_childs.erase(it);
0741 delete _elem;
0742 break;
0743 }
0744 }}
0745 }
0746
0747 void delete_element(element* a_element) {
0748 tools_lforit(ielem*,m_childs,it) {
0749 if(element* _elem = id_cast<ielem,element>(*(*it))) {
0750 if(_elem==a_element) {
0751 m_childs.erase(it);
0752 delete _elem;
0753 break;
0754 }
0755 }}
0756 }
0757
0758 void delete_sub_trees(){
0759 std::list<ielem*>::iterator it;
0760 for(it=m_childs.begin();it!=m_childs.end();) {
0761 if(tree* _tree = id_cast<ielem,tree>(*(*it))) {
0762 it = m_childs.erase(it);
0763 delete _tree;
0764 } else {
0765 it++;
0766 }
0767 }
0768 }
0769
0770 void delete_sub_elems(){
0771 std::list<ielem*>::iterator it;
0772 for(it=m_childs.begin();it!=m_childs.end();) {
0773 if(element* _elem = id_cast<ielem,element>(*(*it))) {
0774 it = m_childs.erase(it);
0775 delete _elem;
0776 } else {
0777 it++;
0778 }
0779 }
0780 }
0781
0782 const tree* find_by_element_in_same_level(const std::string& a_name,
0783 const std::string& a_value) const {
0784 // Look children :
0785 tools_lforcit(ielem*,m_childs,it) {
0786 if(tree* _tree = id_cast<ielem,tree>(*(*it))) {
0787 std::string _s;
0788 if(_tree->element_value(a_name,_s) && (a_value==_s)) return _tree;
0789 }}
0790 return 0;
0791 }
0792
0793 bool element_value_boolean(const std::string& a_name,bool& a_value) const {
0794 std::string value;
0795 if(!element_value(a_name,value)) return false;
0796 return to(value,a_value);
0797 }
0798
0799 void update_tree(const tree& a_old) {
0800 // We map the opened elements in the old tree within this tree.
0801 // Algorithm based on the existence of a "label" element.
0802 tools_lforit(ielem*,m_childs,it) {
0803 if(tree* _tree = id_cast<ielem,tree>(*(*it))) {
0804 std::string slabel;
0805 if(_tree->element_value("label",slabel)) {
0806 // Try to find a same label in the same level :
0807 const tree* item =
0808 a_old.find_by_element_in_same_level("label",slabel);
0809 if(item) {
0810 bool sopened;
0811 if(item->element_value_boolean("opened",sopened) && sopened) {
0812 _tree->set_element_value("opened","true");
0813 }
0814 if(a_old.number_of_trees()) _tree->update_tree(*item);
0815 }
0816 }
0817 }}
0818 }
0819
0820 //////////////////////////////////////////////////
0821 /// end osc //////////////////////////////////////
0822 //////////////////////////////////////////////////
0823
0824 ///////////////////////////////////////////////////////
0825 /// sub trees /////////////////////////////////////////
0826 ///////////////////////////////////////////////////////
0827
0828 tree* parent() const {return m_parent;}
0829
0830 void set_parent(tree* a_parent) {m_parent = a_parent;}
0831
0832 unsigned int number_of_trees() const {
0833 unsigned int number = 0;
0834 tools_lforcit(ielem*,m_childs,it) {
0835 if(id_cast<ielem,tree>(*(*it))) number++;
0836 }
0837 return number;
0838 }
0839
0840 void remove_child(tree*& a_tree,bool a_delete = true){
0841 m_childs.remove(a_tree);
0842 if(a_delete) {
0843 delete a_tree;
0844 a_tree = 0;
0845 }
0846 }
0847
0848 /*
0849
0850 bool is_first_child(const tree& a_tree) {
0851 if(m_children.empty()) return false;
0852 return ( (*(m_children.begin()))==&a_tree) ? true : false;
0853 }
0854
0855 bool is_last_child(const tree& a_tree) {
0856 if(m_children.empty()) return false;
0857 return ( m_children.back()==&a_tree) ? true : false;
0858 }
0859 */
0860
0861 /* TOOLS_STL : no std::list::insert.
0862 void add_after(tree* a_tree,tree* a_entry){
0863 tools_lforit(tree*,m_children,it) {
0864 if((*it)==a_tree) {
0865 m_children.insert(it,a_entry);
0866 return;
0867 }
0868 }
0869 }
0870
0871 //TOOLS_STL : no std::list::iterator::operator--.
0872
0873 tree* previous_child(const tree& a_tree){
0874 tools_lforit(tree*,m_children,it) {
0875 if((*it)==&a_tree) {
0876 if(it==m_children.begin()) return 0;
0877 --it;
0878 return *it;
0879 }
0880 }
0881 return 0;
0882 }
0883
0884 tree* next_child(const tree& a_tree){
0885 tools_lforit(tree*,m_children,it) {
0886 if((*it)==&a_tree) {
0887 std::list<tree*>::iterator last = m_children.end();
0888 --last;
0889 if(it==last) return 0;
0890 ++it;
0891 return *it;
0892 }
0893 }
0894 return 0;
0895 }
0896 */
0897
0898 void set_data(void* a_data_1,void* a_data_2,int a_data_int) {
0899 m_data_1 = a_data_1;
0900 m_data_2 = a_data_2;
0901 m_data_int = a_data_int;
0902 }
0903 void get_data(void*& a_data_1,void*& a_data_2,int& a_data_int) const {
0904 a_data_1 = m_data_1;
0905 a_data_2 = m_data_2;
0906 a_data_int = m_data_int;
0907 }
0908 void* get_data1() const {return m_data_1;}
0909 void* get_data2() const {return m_data_2;}
0910 int get_data_int() const {return m_data_int;}
0911 void set_depth(unsigned int a_depth) {m_depth = a_depth;}
0912 unsigned int depth() const {return m_depth;}
0913 void set_save_flag(bool a_value) {m_save = a_value;}
0914 bool save_flag() const {return m_save;}
0915 void set_file(const std::string& a_file) {m_file = a_file;}
0916 const std::string& file() const {return m_file;}
0917
0918 protected:
0919 void clear(){
0920 m_atbs.clear();
0921
0922 // TOOLS_STL : no std::list::erase.
0923 //{std::list<tree*>::iterator it;
0924 // for(it=m_children.begin();
0925 // it!=m_children.end();
0926 // it = m_children.erase(it))
0927 // delete (*it);}
0928 //
0929 //{std::list<element*>::iterator it;
0930 // for(it=m_elems.begin();it!=m_elems.end();it = m_elems.erase(it))
0931 // delete (*it);}
0932
0933 while(!m_childs.empty()) {
0934 ielem* item = m_childs.front();
0935 m_childs.remove(item);
0936 delete item;
0937 }
0938 }
0939
0940 protected:
0941 std::string m_tag_name;
0942 factory& m_factory;
0943 tree* m_parent;
0944 //std::list<tree*> m_children;
0945 //std::list<element*> m_elems;
0946 std::list<ielem*> m_childs;
0947 std::vector<atb> m_atbs;
0948 std::string m_file;
0949 bool m_save;
0950 void* m_data_1;
0951 void* m_data_2;
0952 int m_data_int;
0953 int m_depth;
0954 };
0955
0956 class looper {
0957 public:
0958 looper(const tree& a_tree)
0959 :m_it(a_tree.childs().begin())
0960 ,m_end(a_tree.childs().end())
0961 {}
0962 virtual ~looper(){}
0963 protected:
0964 looper(const looper& a_from)
0965 :m_it(a_from.m_it)
0966 ,m_end(a_from.m_end)
0967 {}
0968 looper& operator=(const looper&){return *this;}
0969 public:
0970 tree* next_tree() {
0971 for(;m_it!=m_end;++m_it) {
0972 tree* _tree = id_cast<ielem,tree>(*(*m_it));
0973 if(_tree) {m_it++;return _tree;}
0974 }
0975 return 0;
0976 }
0977 element* next_element() {
0978 for(;m_it!=m_end;++m_it) {
0979 element* _elem = id_cast<ielem,element>(*(*m_it));
0980 if(_elem) {m_it++;return _elem;}
0981 }
0982 return 0;
0983 }
0984 protected:
0985 std::list<ielem*>::const_iterator m_it;
0986 std::list<ielem*>::const_iterator m_end;
0987 };
0988
0989 class default_factory : public virtual factory {
0990 #ifdef TOOLS_MEM
0991 TOOLS_SCLASS(tools::xml::default_factory)
0992 #endif
0993 public:
0994 virtual tree* create(const std::string& a_tag_name,const std::vector<tree::atb>& a_atbs,tree* a_parent) {
0995 // It does not add the new tree in parent.
0996 tree* itemML = new tree(a_tag_name,*this,a_parent);
0997 itemML->set_attributes(a_atbs);
0998 return itemML;
0999 }
1000 public:
1001 default_factory(){
1002 #ifdef TOOLS_MEM
1003 mem::increment(s_class().c_str());
1004 #endif
1005 }
1006 virtual ~default_factory(){
1007 #ifdef TOOLS_MEM
1008 mem::decrement(s_class().c_str());
1009 #endif
1010 }
1011 public:
1012 default_factory(const default_factory& a_from)
1013 :factory(a_from){
1014 #ifdef TOOLS_MEM
1015 mem::increment(s_class().c_str());
1016 #endif
1017 }
1018 default_factory& operator=(const default_factory&){return *this;}
1019 };
1020
1021 }}
1022
1023 #endif