gKitGL
IOManager.h
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
 All Classes Namespaces Functions Variables Typedefs Enumerator Friends