core/vsl/vsl_binary_loader.h
Go to the documentation of this file.
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_