gKitGL
|
00001 00002 #ifndef _IOMANAGER_H 00003 #define _IOMANAGER_H 00004 00005 #include <string> 00006 #include <map> 00007 00008 //~ #define VERBOSE_DEBUG 1 00009 00010 #include "IOResource.h" 00011 00012 #ifdef VERBOSE_DEBUG 00013 #include <cstdio> 00014 #include <typeinfo> 00015 00016 #ifdef __GLIBCXX__ 00017 #include <cxxabi.h> 00018 #include <cstdlib> 00019 #include <cstring> 00020 00021 //! decode les symboles g++ et libere la chaine de caracteres allouee par abi::__cxa_demangle 00022 class demangle 00023 { 00024 char *name; 00025 00026 public: 00027 demangle( const char *type_name ) 00028 : 00029 name(NULL) 00030 { 00031 int status; 00032 name= abi::__cxa_demangle(type_name, NULL, NULL, &status); 00033 if(status != 0) 00034 name= strdup(type_name); 00035 } 00036 00037 ~demangle( ) 00038 { 00039 if(name != NULL) 00040 free(name); 00041 } 00042 00043 operator const char *( ) const 00044 { 00045 return name; 00046 } 00047 00048 operator char *( ) 00049 { 00050 return name; 00051 } 00052 }; 00053 #else 00054 //! meme interface pour decoder les symboles g++ sur les autres plateformes. mais ne fait rien. 00055 class demangle 00056 { 00057 const char *name; 00058 00059 public: 00060 demangle( const char *type_name ) 00061 : 00062 name(type_name) 00063 {} 00064 00065 ~demangle( ) {} 00066 00067 operator const char *( ) const 00068 { 00069 return name; 00070 } 00071 00072 operator const char *( ) 00073 { 00074 return name; 00075 } 00076 }; 00077 #endif 00078 #endif // verbose_debug / demangle 00079 00080 00081 namespace gk { 00082 00083 namespace io { 00084 00085 struct object_name 00086 { 00087 std::string filename; 00088 std::string name; 00089 00090 object_name( const std::string& _file, const std::string& _name ) 00091 : 00092 filename(_file), 00093 name(_name) 00094 {} 00095 00096 bool operator< ( const object_name& b ) const 00097 { 00098 int cmp= filename.compare(b.filename); 00099 if(cmp < 0) 00100 return true; 00101 else if(cmp > 0) 00102 return false; 00103 else 00104 return (name < b.name); 00105 } 00106 }; 00107 00108 template< typename Object > 00109 struct object_info 00110 { 00111 IOName ioname; 00112 Object *object; 00113 00114 object_info( const IOName& _name, Object *_object ) 00115 : 00116 ioname(_name), 00117 object(_object) 00118 {} 00119 }; 00120 00121 } // namespace io 00122 00123 00124 //! manager pour les 'objets' importes a partir d'un fichier. 00125 //! object doit deriver de IOResource. 00126 template< class Object > 00127 class IOManager 00128 { 00129 // non copyable 00130 IOManager( const IOManager& ); 00131 IOManager& operator=( const IOManager& ); 00132 00133 protected: 00134 //! constructeur. 00135 IOManager( ) 00136 : 00137 m_names_map(), 00138 m_objects_map(), 00139 m_objects() 00140 {} 00141 00142 //! destructeur. 00143 virtual ~IOManager( ) 00144 { 00145 int n= (int) m_objects.size(); 00146 for(int i= 0; i < n; i++) 00147 delete m_objects[i].object; 00148 } 00149 00150 typedef io::object_name object_name; 00151 typedef std::map<object_name, int> names_map_type; 00152 names_map_type m_names_map; 00153 00154 typedef std::map<Object *, int> objects_map_type; 00155 objects_map_type m_objects_map; 00156 00157 typedef io::object_info<Object> object_info; 00158 std::vector< object_info > m_objects; 00159 00160 object_info *find_info( const std::string& filename, const std::string& name ) 00161 { 00162 typename names_map_type::iterator 00163 found= m_names_map.find( object_name(filename, name) ); 00164 00165 if(found == m_names_map.end()) 00166 return NULL; 00167 else 00168 return &m_objects[found->second]; 00169 } 00170 00171 object_info *find_object( Object *object ) 00172 { 00173 typename objects_map_type::iterator 00174 found= m_objects_map.find( object ); 00175 00176 if(found == m_objects_map.end()) 00177 return NULL; 00178 else 00179 return &m_objects[found->second]; 00180 } 00181 00182 public: 00183 //! reference un nouvel 'objet' par son nom et le nom du fichier d'import. 00184 Object *insert( Object *object, const IOFileInfo& handle, const std::string& name= "" ) 00185 { 00186 if(object == NULL) 00187 return NULL; 00188 00189 #ifdef VERBOSE_DEBUG 00190 printf("IOManager<%s> %p::insert( ): object %p '%s', filename '%s'\n", 00191 (const char *) demangle(typeid(Object).name()), this, 00192 object, name.c_str(), handle.file->filename.c_str()); 00193 #endif 00194 00195 m_names_map.insert( std::make_pair( object_name(handle.filename(), name), m_objects.size() )); 00196 m_objects_map.insert( std::make_pair( object, m_objects.size() )); 00197 m_objects.push_back( object_info( IOName(handle, name), object )); 00198 return object; 00199 } 00200 00201 //! \todo temporaire le temps de porter les autres IOMachins 00202 Object *insert( Object *object, const std::string& filename, const std::string& name= "" ) 00203 { 00204 #ifdef VERBOSE_DEBUG 00205 printf("IOManager<%s> %p::insert( ): object %p '%s', filename '%s'\n", 00206 (const char *) demangle(typeid(Object).name()), this, 00207 object, name.c_str(), filename.c_str()); 00208 #endif 00209 00210 IOFileInfo handle= IOFileManager::manager().file(filename); 00211 if(handle.isValid() == false) 00212 return NULL; 00213 00214 return insert(object, handle, name); 00215 } 00216 00217 //! recherche un 'objet' deja importe. 00218 Object *find( const IOFileInfo& handle, const std::string& name= "" ) 00219 { 00220 object_info *found= find_info(handle.filename(), name); 00221 #ifdef VERBOSE_DEBUG 00222 printf("IOManager<%s> %p::find( ): object '%s', filename '%s'... ", 00223 (const char *) demangle(typeid(Object).name()), this, 00224 name.c_str(), handle.filename().c_str()); 00225 if(found != NULL) 00226 printf("found object %p done.\n", found->object); 00227 else 00228 printf("failed.\n"); 00229 #endif 00230 00231 if(found == NULL) 00232 return NULL; 00233 return found->object; 00234 } 00235 00236 //! recherche un objet deja importe. 00237 Object *find( const std::string& filename, const std::string& name= "" ) 00238 { 00239 object_info *found= find_info(filename, name); 00240 #ifdef VERBOSE_DEBUG 00241 printf("IOManager<%s> %p::find( ): object '%s', filename '%s'... ", 00242 (const char *) demangle(typeid(Object).name()), this, 00243 name.c_str(), filename.c_str()); 00244 if(found != NULL) 00245 printf("found object %p done.\n", found->object); 00246 else 00247 printf("failed.\n"); 00248 #endif 00249 00250 if(found == NULL) 00251 return NULL; 00252 return found->object; 00253 } 00254 00255 //! recherche le nom et le nom du fichier d'un 'objet' deja importe. 00256 IOName *find( Object *object ) 00257 { 00258 object_info *found= find_object(object); 00259 #ifdef VERBOSE_DEBUG 00260 printf("IOManager<%s> %p::find( ): object %p... ", 00261 (const char *) demangle(typeid(Object).name()), this, object); 00262 00263 if(found != NULL) 00264 printf("found object '%s', filename '%s' done.\n", 00265 found->ioname.name().c_str(), found->ioname.filename().c_str()); 00266 else 00267 printf("failed.\n"); 00268 #endif 00269 00270 if(found == NULL) 00271 return NULL; 00272 return &found->ioname; 00273 } 00274 00275 //! renvoie l'etat du fichier associe a un objet gere par le manager. 00276 //! -1 en cas d'erreur, 0 pas de modifications, 1 le fichier a ete modifie depuis sa lecture par le manager. 00277 int modified( Object *object ) 00278 { 00279 object_info *found= find_object(object); 00280 if(found == NULL || found->ioname->handle().isValid() == false) 00281 { 00282 // le fichier n'est pas reference ... pas lu en passant par le manager. 00283 printf("modified %p... failed.\n", object); 00284 return -1; 00285 } 00286 00287 // verifie la date et la taille du fichier 00288 return found->ioname->handle().modified(); 00289 } 00290 00291 //! renvoie l'etat d'un fichier charge par le manager. 00292 //! -1 en cas d'erreur, 0 pas de modifications, 1 le fichier a ete modifie depuis sa lecture par le manager. 00293 int modified( const std::string& filename, const std::string& name= "" ) 00294 { 00295 object_info *found= find_info(filename, name); 00296 if(found == NULL || found->ioname->handle().isValid() == false) 00297 { 00298 // le fichier n'est pas reference ... pas lu en passant par le manager. 00299 printf("modified '%s'... failed.\n", filename.c_str()); 00300 return -1; 00301 } 00302 00303 // verifie la date et la taille du fichier 00304 return found->ioname->handle().modified(); 00305 } 00306 00307 //~ //! detruit un objet deja charge. 00308 //~ int release( Object *object ) 00309 //~ { 00310 //~ delete object; 00311 //~ return 0; 00312 //~ } 00313 }; 00314 00315 //~ #undef VERBOSE_DEBUG 00316 } // namespace 00317 00318 #endif