00001 #ifndef IOKERNEL__CASCADINGMAP_H 00002 #define IOKERNEL__CASCADINGMAP_H 00003 00004 #include "iokernel/object.h" 00005 #include "iokernel/iokernel_forwarders.h" 00006 #include "iokernel/object_factory.h" 00007 #include "iokernel/meta_class.h" 00008 #include "suif_env.h" 00009 #include "common/suif_vector.h" 00010 00048 template < class T > 00049 class CascadingMap { 00050 public: 00051 CascadingMap( SuifEnv* suif, T defaultvalue ); 00052 ~CascadingMap(); 00053 00054 void assign( const LString &className, T data); 00055 00056 // returns defaultvalue if not found; 00057 T lookup( const Object* object ); 00058 00059 // low level interface 00060 T lookup( const MetaClass* metaClass ); 00061 void assign( MetaClass* mc, T newdata ); 00062 00063 private: 00064 T defaultvalue; 00065 suif_vector<T>* entries; 00066 SuifEnv* suif; 00067 suif_vector<bool>* cached; 00068 suif_vector<bool>* valid; 00069 void clear_cache(); 00070 void expand_to(MetaClassId to_id); 00071 private: 00072 CascadingMap(const CascadingMap &other); 00073 CascadingMap& operator=(const CascadingMap &other); 00074 }; 00075 00076 00077 class SuifEnv; 00078 00079 template < class T > 00080 CascadingMap<T>::CascadingMap( SuifEnv* suif_env, T defaultvalue0 ) : 00081 defaultvalue(defaultvalue0), entries(0), suif(suif_env), cached(0), 00082 valid(0) 00083 { 00084 // this->suif = suif; 00085 unsigned num = suif->get_object_factory()->get_last_id(); 00086 entries = new suif_vector<T>( num ); 00087 cached = new suif_vector<bool>( num ); 00088 valid = new suif_vector<bool>( num ); 00089 for (unsigned i = 0; i < num; i++) { 00090 (*entries)[i] = defaultvalue; 00091 (*cached)[i] = false; 00092 (*valid)[i] = false; 00093 } 00094 } 00095 00096 template< class T > 00097 void CascadingMap<T>::clear_cache() { 00098 unsigned num = cached->size(); 00099 for (unsigned i = 0; i < num; i++) { 00100 (*cached)[i] = false; 00101 } 00102 } 00103 00104 template < class T > 00105 CascadingMap<T>::~CascadingMap() { 00106 delete entries; 00107 delete cached; 00108 delete valid; 00109 } 00110 00111 template < class T > 00112 void CascadingMap<T>::assign( const LString &className, 00113 T data ) { 00114 MetaClass *mc = suif->get_object_factory()->lookupMetaClass( className ); 00115 suif_assert_message( mc, 00116 ("No metaclass registered for %s." 00117 "Perhaps another dll is required.", 00118 className.c_str() )); 00119 assign(mc, data); 00120 } 00121 00122 template < class T > 00123 void CascadingMap<T>::expand_to( MetaClassId id ) { 00124 while( id >= (MetaClassId)entries->size()){ 00125 entries->push_back(defaultvalue); 00126 valid->push_back(false); 00127 cached->push_back(false); 00128 } 00129 return; 00130 } 00131 00132 00133 template < class T > 00134 void CascadingMap<T>::assign( MetaClass* mc, T data ) { 00135 clear_cache(); 00136 suif_assert_message( mc, 00137 ("Cascading Map can not Map the NULL MetaClass\n")); 00138 MetaClassId id = mc->get_meta_class_id(); 00139 00140 expand_to(id); 00141 00142 (*entries)[id] = data; 00143 (*valid)[id] = true; 00144 } 00145 00146 template < class T > 00147 T CascadingMap<T>::lookup( const Object* object ) { 00148 return lookup( object->get_meta_class() ); 00149 } 00150 00151 template < class T > 00152 T CascadingMap<T>::lookup( const MetaClass* mc ) { 00153 MetaClassId id = mc->get_meta_class_id(); 00154 expand_to(id); 00155 00156 if ((*valid)[id] || (*cached)[id]) { 00157 return (*entries)[ id ]; 00158 } else { 00159 MetaClass *parent = mc->get_link_meta_class(); 00160 if (parent) { 00161 T res = lookup(parent); 00162 (*entries)[id] = res; 00163 (*cached)[id] = true; 00164 return res; 00165 } else { 00166 (*entries)[id] = defaultvalue; 00167 (*cached)[id] = true; 00168 return defaultvalue; 00169 } 00170 } 00171 } 00172 00173 #endif