// Copyright (C) 2010, Guy Barrand. All rights reserved. // See the file tools.license for terms. #ifndef tools_sg_holder #define tools_sg_holder // class to manage an object. // Only one holder owns the object. In case // of holder copy(), the new holder receives a null object. #include "node" #include "sf_string" namespace tools { namespace sg { class base_holder : public node { TOOLS_NODE(base_holder,tools::sg::base_holder,node) public: base_holder(const std::string& a_name):parent(),m_name(a_name) {} virtual ~base_holder(){} public: base_holder(const base_holder& a_from):parent(a_from),m_name(a_from.m_name) {} base_holder& operator=(const base_holder& a_from){ parent::operator=(a_from); m_name = a_from.m_name; return *this; } public: const std::string& name() const {return m_name;} protected: std::string m_name; }; template class holder : public base_holder { typedef base_holder parent; public: //WARNING : we do not put the T class name in the name of this class. // We put it in the class_name field. // We do that because of the bsg file format in order to be able // to read back the object without having the T class around. TOOLS_T_SCLASS(T,tools::sg::holder) public: virtual void* cast(const std::string& a_class) const { if(void* p = cmp_cast< holder >(this,a_class)) {return p;} return parent::cast(a_class); } virtual node* copy() const {return new holder(*this);} virtual const std::string& s_cls() const {return s_class();} public: sf_string class_name; public: virtual const desc_fields& node_desc_fields() const { TOOLS_FIELD_DESC_NODE_CLASS(tools::sg::holder) static const desc_fields s_v(parent::node_desc_fields(),1, //WARNING : take care of count. TOOLS_ARG_FIELD_DESC(class_name) ); return s_v; } private: void add_fields(){ add_field(&class_name); } public: holder(T* a_obj = 0,const std::string& a_name = "",bool a_own=true) :parent(a_name) ,class_name(T::s_class()) ,m_obj(a_obj) //it takes a_obj ownership. ,m_own(a_own) { add_fields(); } virtual ~holder(){if(m_own) delete m_obj;} public: //any copy of a holder does NOT own any object (and we empty the name). holder(const holder& a_from) :parent(a_from) ,class_name(std::string()) ,m_obj(0) ,m_own(false) { parent::m_name.clear(); add_fields(); } holder& operator=(const holder& a_from){ parent::operator=(a_from); class_name.value().clear(); m_obj = 0; m_own = false; parent::m_name.clear(); return *this; } public: const T* object() const {return m_obj;} T* object() {return m_obj;} protected: T* m_obj; bool m_own; }; template inline holder* cast_holder(node& a_node) { typedef holder h_t; h_t* _h = (h_t*)a_node.cast(h_t::s_class()); if(!_h) return 0; return (_h->class_name.value()==T::s_class()?_h:0); } template inline const holder* cast_holder(const node& a_node) { typedef holder h_t; h_t* _h = (h_t*)a_node.cast(h_t::s_class()); if(!_h) return 0; return (_h->class_name.value()==T::s_class()?_h:0); } template inline const T* cast_holder_object(const node& a_node) { typedef holder h_t; h_t* _h = (h_t*)a_node.cast(h_t::s_class()); if(!_h) return 0; return (_h->class_name.value()==T::s_class()?_h->object():0); } template inline T* cast_holder_object(node& a_node) { typedef holder h_t; h_t* _h = (h_t*)a_node.cast(h_t::s_class()); if(!_h) return 0; return (_h->class_name.value()==T::s_class()?_h->object():0); } template inline void remove_holders(std::vector& a_vec){ typedef holder h_t; std::vector::iterator it; for(it=a_vec.begin();it!=a_vec.end();) { if(h_t* h = cast_holder(*(*it))){ it = a_vec.erase(it); delete h; continue; } ++it; } } template inline void remove_holders(std::vector& a_vec,const std::string& a_name){ typedef holder h_t; std::vector::iterator it; for(it=a_vec.begin();it!=a_vec.end();) { if(h_t* h = cast_holder(*(*it))){ if(h->name()==a_name) { it = a_vec.erase(it); delete h; continue; } } ++it; } } template inline T* find_holder(std::vector& a_vec,const std::string& a_name) { //return the first named found. typedef holder h_t; std::vector::iterator it; for(it=a_vec.begin();it!=a_vec.end();++it) { if(h_t* h = cast_holder(*(*it))){ if(h->name()==a_name) return h->object(); } } return 0; } template inline T* find_first_holder(std::vector& a_vec){ //return the first T found. typedef holder h_t; std::vector::iterator it; for(it=a_vec.begin();it!=a_vec.end();++it) { if(h_t* h = cast_holder(*(*it))) return h->object(); } return 0; } }} #endif