vsl_clipon_binary_loader.h
Go to the documentation of this file.
1 // This is core/vsl/vsl_clipon_binary_loader.h
2 #ifndef vsl_clipon_binary_loader_h_
3 #define vsl_clipon_binary_loader_h_
4 //:
5 // \file
6 
7 #include <vector>
8 #include <string>
10 #include <vsl/vsl_binary_io.h>
11 #ifdef _MSC_VER
12 # include <vcl_msvc_warnings.h>
13 #endif
14 
15 //: Class to load objects by baseclass pointer using `clipon' classes
16 // An example of a singleton design pattern for loading
17 // a DerivedClass from a stream into a BaseClass*.
18 // All we are given is a BaseClass* into which
19 // the object has to be loaded but we can only tell
20 // what sort of object it is from the name information
21 // stored in the stream.
22 // We assume the existence of a polymorphic hierarchy of `clipon'
23 // loader objects, eg BaseClassIO and DerivedClassIO, one per
24 // class in the hierarchy derived from BaseClass. Each XXXXIO
25 // class is able to read and write the corresponding XXXX class.
26 //
27 // BaseClassIO must implement the following functions:
28 // \code
29 // //: Base for objects which provide IO for classes derived from BaseClass
30 // class BaseClassIO
31 // {
32 // public:
33 // //: Create new object of type BaseClass on heap
34 // virtual BaseClass* new_object() const;
35 // //: Write derived class to os using baseclass reference
36 // virtual void b_write_by_base(vsl_b_ostream& os,
37 // const BaseClass& base) const;
38 // //: Write derived class to os using baseclass reference
39 // virtual void b_read_by_base(vsl_b_istream& is, BaseClass& base) const;
40 // //: Print summary to stream by BaseClass pointer
41 // void vsl_print_summary(vsl_b_ostream &os, const BaseClass * b);
42 // //: Copy this object onto the heap and return a pointer
43 // virtual BaseClassIO* clone() const;
44 // //: Return name of class for which this object provides IO
45 // virtual std::string target_classname() const;
46 // //: Return true if b is of class target_classname()
47 // // Typically this will just be "return b.is_a()==target_classname()"
48 // // However, third party libraries may use a different system
49 // virtual bool is_io_for(const BaseClass& b) const;
50 // };
51 // \endcode
52 //
53 // To handle the actual IO we define a loader
54 // which has a list of BaseClassIO pointers,
55 // and the ChainOfResponsibility (Design Pattern)
56 // approach is used to load the object i.e. each
57 // io->target_classname() is matched against the string on the stream
58 // until we find a match or run out of pointers. If
59 // a pointer is found which matches the string on
60 // the stream, we use it to create an object on the
61 // heap (using io->new_object()) and then load the
62 // data into that from the stream (using io->b_read_by_base())
63 //
64 // We use a singleton so that there is only one list of
65 // concrete derived classes which can be added
66 // to for loading purposes. If you derive a new
67 // class you just have to append it to the list of
68 // classes of the singleton, viz:
69 // vsl_clipon_binary_loader<B,IO>::instance().add(my_object)
70 //
71 // For examples of usage please see vsl/tests/test_clipon_polymorphic_io.cxx
72 // or look in the Binary IO chapter of the VXL book.
73 //
74 // To indicate a null pointer (0), the string "VSL_NULL_PTR" is saved
75 // to the stream.
76 // All loader singletons can be deleted using vsl_delete_all_loaders()
77 template<class BaseClass, class BaseClassIO>
79 {
80  //: the singleton object
82 
83  //: List of object loaders
84  std::vector<BaseClassIO*> object_io_;
85 
86  //: Return index associated with given object name
87  int index_for_name(const std::string& name) const;
88 
89  public:
90  //: Constructor
91  vsl_clipon_binary_loader() = default;
92 
93  //: Destructor
94  ~vsl_clipon_binary_loader() override;
95 
96  //: Returns the instance variable for the singleton.
98 
99  //: Remove all example objects
100  void make_empty();
101 
102  //: Add example object to list of those that can be loaded
103  void add( const BaseClassIO& b);
104 
105  //: Return current list of individual IO objects
106  const std::vector<BaseClassIO*>& object_io() const { return object_io_; }
107 
108  //: Return IO object for given named class
109  // Aborts if not available
110  const BaseClassIO& object_io(const std::string& name) const;
111 
112  //: Return IO object that can deal with given class
113  const BaseClassIO& io_for_class(const BaseClass& b) const;
114 
115  //: Reads object from stream and sets base class pointer
116  // Determines which derived class object on stream belongs
117  // to, loads it and sets b to be a pointer to it.
118  // (Class must be one given to Loader by the add method).
119  // If is indicates a NULL pointer, b will be set to NULL.
120  // If b not initially NULL, *b will be deleted.
121  void read_object( vsl_b_istream& is, BaseClass*& b);
122 
123  //: Writes object to stream given base class pointer
124  // Determines which derived class object is
125  // and calls the appropriate write function.
126  // (Class must be one given to Loader by the add method).
127  // If b==0, a suitable string will be saved
128  void write_object( vsl_b_ostream& is, const BaseClass* b);
129 
130  //: Prints summary of object state to stream given base class pointer
131  // Determines which derived class object is
132  // and calls the appropriate print summary function.
133  // (Class must be one given to Loader by the add method).
134  // If b==0, a suitable string will be saved
135  void print_object_summary( std::ostream& os, const BaseClass* b);
136 };
137 
138 
139 #if 0
140 //: Loads object and sets base class pointer
141 // Determines which derived class object on bfs belongs
142 // to, loads it and sets b to be a pointer to it.
143 // (Class must be one given to Loader by the append method).
144 // If bfs indicates a NULL pointer, b will be set to NULL.
145 // If b not initially NULL, *b will be deleted.
146 inline void vsl_b_read( vsl_b_istream& bfs, BaseClass*& b)
147 {
149  instance().load_object(bfs,b);
150 }
151 #endif // 0
152 
153 #endif // vsl_clipon_binary_loader_h_
std::vector< BaseClassIO * > object_io_
List of object loaders.
A binary output adaptor for any std::ostream.
Definition: vsl_binary_io.h:37
vsl_clipon_binary_loader()=default
Constructor.
static vsl_clipon_binary_loader< BaseClass, BaseClassIO > & instance()
Returns the instance variable for the singleton.
static vsl_clipon_binary_loader< BaseClass, BaseClassIO > * instance_
the singleton object.
Base class for vsl_binary_loader objects.
void write_object(vsl_b_ostream &is, const BaseClass *b)
Writes object to stream given base class pointer.
const std::vector< BaseClassIO * > & object_io() const
Return current list of individual IO objects.
void print_object_summary(std::ostream &os, const BaseClass *b)
Prints summary of object state to stream given base class pointer.
~vsl_clipon_binary_loader() override
Destructor.
void add(const BaseClassIO &b)
Add example object to list of those that can be loaded.
int index_for_name(const std::string &name) const
Return index associated with given object name.
const BaseClassIO & io_for_class(const BaseClass &b) const
Return IO object that can deal with given class.
void make_empty()
Remove all example objects.
void vsl_b_read(vsl_b_istream &is, char &n)
Read char from vsl_b_istream.
An adaptor for any std::istream to make it suitable for binary input.
void read_object(vsl_b_istream &is, BaseClass *&b)
Reads object from stream and sets base class pointer.
Class to load objects by baseclass pointer using ‘clipon’ classes.
Set of functions, and objects to perform binary IO.