]> git.tdb.fi Git - libs/datafile.git/blob - source/loader.h
Consider full statement signature when dealing with auxiliary loaders
[libs/datafile.git] / source / loader.h
1 #ifndef MSP_DATAFILE_LOADER_H_
2 #define MSP_DATAFILE_LOADER_H_
3
4 #include <map>
5 #include <msp/io/file.h>
6 #include "loaderaction.h"
7 #include "parser.h"
8 #include "statement.h"
9
10 namespace Msp {
11 namespace DataFile {
12
13 /**
14 Base class for data loaders.  This class only provides core functionality.
15 You'll almost certainly want to use one of the BasicLoader classes instead.
16
17 Under normal circumstances, a class capable of being loaded should have a
18 nested typed called Loader which resolves to a descendant of this class.  If
19 another structure is used, the loader object must be constructed manually.
20
21 A loader class should execute one or more calls to the various add() functions
22 to register actions with expected keywords.  Currently possible actions are
23 calling a function of the loader, storing values in member variables of an
24 object and ignoring the statement.  If a unexpected keyword is encountered, an
25 exception is thrown and the loading is aborted.
26
27 A sub-object can be loaded with one of the load_sub functions.
28
29 When loading has finished successfully, the virtual function finish() is
30 called.  Any post-processing of the data should be placed here and not in the
31 destructor.
32
33 See also classes ObjectLoader and CollectionObjectLoader in objectloader.h.
34 */
35 class Loader
36 {
37 private:
38         struct ActionKey
39         {
40                 std::string keyword;
41                 std::string signature;
42
43                 ActionKey(const std::string &, const std::string &);
44
45                 bool operator<(const ActionKey &) const;
46         };
47
48         typedef std::map<ActionKey, LoaderAction *> ActionMap;
49
50         ActionMap actions;
51         const Statement *cur_st;
52         bool sub_loaded;
53         std::list<Loader *> aux_loaders;
54 protected:
55         bool check_sub_loads;
56
57         Loader();
58 public:
59         virtual ~Loader();
60
61         /** Loads statements from a parser. */
62         void load(Parser &p);
63
64 private:
65         /** Loads data from a statement. */
66         void load(const Statement &st);
67
68         /** Processes a single statement */
69         void load_statement(const Statement &st);
70
71 protected:
72         /** Loads a sub-object from the statement being processed.  The Loader class
73         of the sub-object is automatically used. */
74         template<typename S>
75         void load_sub(S &s)
76         {
77                 typename S::Loader ldr(s);
78                 load_sub_with(ldr);
79         }
80
81         /** Loads a sub-object from the statement being processed with an extra
82         parameter for the Loader.  The Loader class of the sub-object is
83         automatically used. */
84         template<typename S, typename T>
85         void load_sub(S &s, T &p)
86         {
87                 typename S::Loader ldr(s, p);
88                 load_sub_with(ldr);
89         }
90
91         /** Processes the current statement's substatements with another Loader. */
92         void load_sub_with(Loader &);
93
94         /** Adds a keyword that is loaded by calling a function. */
95         template<typename L>
96         void add(const std::string &k, void (L::*func)())
97         { add(k, new LoaderFunc0<L>(func)); }
98
99         template<typename L, typename A0>
100         void add(const std::string &k, void (L::*func)(A0))
101         { add(k, new LoaderFunc1<L, A0>(func)); }
102
103         template<typename L, typename A0, typename A1>
104         void add(const std::string &k, void (L::*func)(A0, A1))
105         { add(k, new LoaderFunc2<L, A0, A1>(func)); }
106
107         template<typename L, typename A0, typename A1, typename A2>
108         void add(const std::string &k, void (L::*func)(A0, A1, A2))
109         { add(k, new LoaderFunc3<L, A0, A1, A2>(func)); }
110
111         template<typename L, typename A0, typename A1, typename A2, typename A3>
112         void add(const std::string &k, void (L::*func)(A0, A1, A2, A3))
113         { add(k, new LoaderFunc4<L, A0, A1, A2, A3>(func)); }
114
115         template<typename L, typename A0, typename A1, typename A2, typename A3, typename A4>
116         void add(const std::string &k, void (L::*func)(A0, A1, A2, A3, A4))
117         { add(k, new LoaderFunc5<L, A0, A1, A2, A3, A4>(func)); }
118
119         /** Adds a keyword that is loaded into a member of the loaded object. */
120         template<typename L, typename T0>
121         void add(const std::string &k, T0 L::*p0)
122         { add(k, new LoadValue1<L, T0>(p0)); }
123
124         template<typename L, typename T0, typename T1>
125         void add(const std::string &k, T0 L::*p0, T1 L::*p1)
126         { add(k, new LoadValue2<L, T0, T1>(p0, p1)); }
127
128         /** Adds a keyword that is recognized but ignored. */
129         void add(const std::string &k)
130         { add(k, 0); }
131
132 private:
133         void add(const std::string &, LoaderAction *);
134
135 protected:
136         void add_auxiliary_loader(Loader &);
137
138 private:
139         bool has_action(const ActionKey &) const;
140         LoaderAction *find_action(const ActionKey &) const;
141
142 protected:
143         /** Returns the source of the statement being processed.  This can be used
144         to implement relative paths in include-like statements.  Note that the
145         source may not necessarily be a file. */
146         const std::string &get_source() const;
147
148         virtual void finish() { }
149 };
150
151
152 /**
153 Loads an object from a file.  The object must have a public Loader class.
154 */
155 template<typename T>
156 void load(T &obj, const std::string &fn)
157 {
158         IO::BufferedFile in(fn);
159
160         Parser parser(in, fn);
161         typename T::Loader loader(obj);
162         loader.load(parser);
163 }
164
165 template<typename T, typename U>
166 void load(T &obj, const std::string &fn, U &arg)
167 {
168         IO::BufferedFile in(fn);
169
170         Parser parser(in, fn);
171         typename T::Loader loader(obj, arg);
172         loader.load(parser);
173 }
174
175 } // namespace DataFile
176 } // namespace Msp
177
178 #endif