00001 // This is core/vsl/vsl_binary_loader.h 00002 #ifndef vsl_binary_loader_h_ 00003 #define vsl_binary_loader_h_ 00004 #ifdef VCL_NEEDS_PRAGMA_INTERFACE 00005 #pragma interface 00006 #endif 00007 //: 00008 // \file 00009 // \brief Loader to do Polymorphic IO. 00010 // \author Ian Scott, Tim Cootes (Manchester) March 2001 00011 // 00012 // You should include this file if you want to do polymorphic IO 00013 // (i.e. save a class by its base-class pointer.) 00014 00015 #include <vsl/vsl_binary_io.h> 00016 #include <vsl/vsl_binary_loader_base.h> 00017 #include <vcl_vector.h> 00018 00019 //: Class to load objects by baseclass pointer. 00020 // An example of a singleton design pattern for loading 00021 // a DerivedClass from a stream into a BaseClass*. 00022 // All we are given is a BaseClass* into which 00023 // the object has to be loaded but we can only tell 00024 // what sort of object it is from the is_a() information 00025 // stored in the stream. To handle this we define a loader 00026 // which has a list of BaseClass pointers, 00027 // and the ChainOfResponsibility (Design Pattern) 00028 // approach is used to load the object i.e. each 00029 // ptr->is_a() is matched against the string on the stream 00030 // until we find a match or run out of pointers. If 00031 // a pointer is found which matches the string on 00032 // the stream, we clone it, use the clone to load the object 00033 // from the stream, then return a pointer to the clone. 00034 // 00035 // We use a singleton so that there is only one list of 00036 // concrete derived classes which can be added 00037 // to for loading purposes. If you derive a new 00038 // class you just have to append it to the list of 00039 // classes of the singleton, viz: 00040 // vsl_binary_loader::instance().append(my_object) 00041 // The BaseClass MUST implement is_a(),is_class(),clone(),b_write() and 00042 // b_read() virtual functions. 00043 // 00044 // vsl_binary_loader.h also provides the function templates for loading 00045 // and saving by base class pointer 00046 // 00047 // All loader singletons can be deleted using vsl_delete_all_loaders() 00048 template<class BaseClass> 00049 class vsl_binary_loader : public vsl_binary_loader_base 00050 { 00051 //: the singleton object 00052 static vsl_binary_loader<BaseClass>* instance_; 00053 00054 //: List of concrete classes that this loader can deal with 00055 vcl_vector<BaseClass*> object_; 00056 00057 public : 00058 //: Constructor 00059 vsl_binary_loader() {} 00060 00061 //: Destructor 00062 ~vsl_binary_loader(); 00063 00064 //: Returns the instance variable for the singleton. 00065 static vsl_binary_loader<BaseClass>& instance(); 00066 00067 //: Remove all example objects 00068 void make_empty(); 00069 00070 //: Add example object to list of those that can be loaded 00071 void add( const BaseClass& b) { object_.push_back(b.clone());} 00072 00073 //: Return current list of class objects which can be loaded 00074 const vcl_vector<BaseClass*>& object() { return object_; } 00075 00076 //: Loads object and sets base class pointer 00077 // Determines which derived class object on is belongs 00078 // to, loads it and sets b to be a pointer to it. 00079 // (Class must be one given to Loader by the add method). 00080 // If is indicates a NULL pointer, b will be set to NULL. 00081 // If b not initially NULL, *b will be deleted. 00082 void load_object( vsl_b_istream& is, BaseClass*& b); 00083 00084 vcl_string is_a() const; 00085 }; 00086 00087 00088 //: Loads object and sets base class pointer 00089 // Determines which derived class object on bfs belongs 00090 // to, loads it and sets b to be a pointer to it. 00091 // (Class must be one given to Loader by the append method). 00092 // If bfs indicates a NULL pointer, b will be set to NULL. 00093 // If b not initially NULL, *b will be deleted. 00094 template<class BaseClass> 00095 inline void vsl_b_read( vsl_b_istream& bfs, BaseClass*& b) 00096 { 00097 vsl_binary_loader<BaseClass>::instance().load_object(bfs,b); 00098 } 00099 00100 //: Binary file stream output operator for pointer to class 00101 // This works correctly even if b is a NULL pointer 00102 template<class BaseClass> 00103 void vsl_b_write(vsl_b_ostream& bfs, const BaseClass* b); 00104 00105 #endif // vsl_binary_loader_h_