]> git.tdb.fi Git - libs/datafile.git/blob - source/loader.h
Cosmetic changes
[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 "meta.h"
8 #include "parser.h"
9 #include "statement.h"
10
11 namespace Msp {
12 namespace DataFile {
13
14 /**
15 Base class for data loaders.  This class only provides core functionality.
16 You'll almost certainly want to use one of the BasicLoader classes instead.
17
18 Under normal circumstances, a class capable of being loaded should have a
19 nested typed called Loader which resolves to a descendant of this class.  If
20 another structure is used, the loader object must be constructed manually.
21
22 A loader class should execute one or more calls to the various add() functions
23 to register actions with expected keywords.  Currently possible actions are
24 calling a function of the loader, storing values in member variables of an
25 object and ignoring the statement.  If a unexpected keyword is encountered, an
26 exception is thrown and the loading is aborted.
27
28 A sub-object can be loaded with one of the load_sub functions.
29
30 When loading has finished successfully, the virtual function finish() is
31 called.  Any post-processing of the data should be placed here and not in the
32 destructor.
33
34 See also classes ObjectLoader and CollectionObjectLoader in objectloader.h.
35 */
36 class Loader
37 {
38 protected:
39         typedef std::map<StatementKey, LoaderAction *> ActionMap;
40
41 private:
42         ActionMap local_actions;
43         ActionMap *actions;
44         Parser *cur_parser;
45         unsigned cur_level;
46         const Statement *cur_st;
47         bool sub_loaded;
48         bool direct;
49         std::vector<Loader *> aux_loaders;
50 protected:
51         bool check_sub_loads;
52
53         Loader();
54 public:
55         virtual ~Loader();
56
57         /** Loads statements from a parser. */
58         void load(Parser &p);
59
60 private:
61         /** Loads data from a statement. */
62         void load(const Statement &st);
63
64         /** Loads statemsnts from a parser, feeding them directly to actions. */
65         void load_direct(Parser &, unsigned);
66
67         /** Processes a single statement */
68         void load_statement(const Statement &st);
69
70 protected:
71         /** Loads a sub-object from the statement being processed.  The Loader class
72         of the sub-object is automatically used. */
73         template<typename S>
74         void load_sub(S &s)
75         {
76                 typename S::Loader ldr(s);
77                 load_sub_with(ldr);
78         }
79
80         /** Loads a sub-object from the statement being processed with an extra
81         parameter for the Loader.  The Loader class of the sub-object is
82         automatically used. */
83         template<typename S, typename T>
84         void load_sub(S &s, T &p)
85         {
86                 typename S::Loader ldr(s, p);
87                 load_sub_with(ldr);
88         }
89
90         /** Processes the current statement's substatements with another Loader. */
91         void load_sub_with(Loader &);
92
93         /** Sets the actions to be used when loading.  If the map is empty,
94         init_actions will be called. */
95         void set_actions(ActionMap &);
96         virtual void init_actions() { }
97
98         /** Adds a keyword that is loaded by calling a function. */
99         template<typename L>
100         void add(const std::string &k, void (L::*func)())
101         { add(k, new LoaderFunc0<L>(func)); }
102
103         template<typename L, typename A0>
104         void add(const std::string &k, void (L::*func)(A0))
105         { add(k, new LoaderFunc1<L, A0>(func)); }
106
107 #if __cplusplus>=201103L
108         template<typename L, typename... Args>
109         void add(const std::string &k, void (L::*func)(Args...))
110         { add(k, new LoaderFuncN<L, Args...>(func)); }
111
112 #else
113         template<typename L, typename A0, typename A1>
114         void add(const std::string &k, void (L::*func)(A0, A1))
115         { add(k, new LoaderFunc2<L, A0, A1>(func)); }
116
117         template<typename L, typename A0, typename A1, typename A2>
118         void add(const std::string &k, void (L::*func)(A0, A1, A2))
119         { add(k, new LoaderFunc3<L, A0, A1, A2>(func)); }
120
121         template<typename L, typename A0, typename A1, typename A2, typename A3>
122         void add(const std::string &k, void (L::*func)(A0, A1, A2, A3))
123         { add(k, new LoaderFunc4<L, A0, A1, A2, A3>(func)); }
124
125         template<typename L, typename A0, typename A1, typename A2, typename A3, typename A4>
126         void add(const std::string &k, void (L::*func)(A0, A1, A2, A3, A4))
127         { add(k, new LoaderFunc5<L, A0, A1, A2, A3, A4>(func)); }
128 #endif
129
130 #if __cplusplus>=201103L
131         /** Adds a keyword that is loaded by calling a function with a bound
132         first argument. */
133         template<typename L, typename B0, typename... Args>
134         void add(const std::string &k, void (L::*func)(B0, Args...), const typename RemoveReference<B0>::Type &b0)
135         { add(k, new LoaderFuncNBound1<L, B0, Args...>(func, b0)); }
136 #endif
137
138         /** Adds a keyword that is loaded into a member of the loaded object. */
139         template<typename L, typename T0>
140         void add(const std::string &k, T0 L::*p0)
141         { add(k, new LoadValue1<L, T0>(p0)); }
142
143         template<typename L, typename T0, typename T1>
144         void add(const std::string &k, T0 L::*p0, T1 L::*p1)
145         { add(k, new LoadValue2<L, T0, T1>(p0, p1)); }
146
147         /** Adds a keyword that is recognized but ignored. */
148         void add(const std::string &k)
149         { add(k, 0); }
150
151 private:
152         void add(const std::string &, LoaderAction *);
153
154 protected:
155         void add_auxiliary_loader(Loader &);
156
157 private:
158         bool has_action(const StatementKey &) const;
159         LoaderAction *find_action(const StatementKey &) const;
160
161 protected:
162         /** Returns the source of the statement being processed.  This can be used
163         to implement relative paths in include-like statements.  Note that the
164         source may not necessarily be a file. */
165         const std::string &get_source() const;
166
167         /** Returns the keyword of the statement being processed.  Can be used to
168         implement dynamic keywords. */
169         const std::string &get_keyword() const;
170
171         virtual void finish() { }
172 };
173
174
175 #if __cplusplus>=201103L
176 /**
177 Loads an object from a file.  The object must have a public Loader class.  Any
178 extra arguments are passed to the Loader constructor.
179 */
180 template<typename T, typename... Args>
181 void load(T &obj, const std::string &fn, Args &... args)
182 {
183         IO::BufferedFile in(fn);
184
185         Parser parser(in, fn);
186         typename T::Loader loader(obj, args...);
187         loader.load(parser);
188 }
189
190 /**
191 Loads an object from a file stored in a collection.  The object must havea
192 public Loader class.  The collection is passed to the Loader constructor,
193 followed by any extra arguments.
194 */
195 template<typename T, typename... Args>
196 void load(T &obj, typename T::Loader::Collection &coll, const std::string &fn, Args &... args)
197 {
198         RefPtr<IO::Seekable> in = coll.open_raw(fn);
199         if(!in)
200                 throw IO::file_not_found(fn);
201
202         Parser parser(*in, fn);
203         typename T::Loader loader(obj, coll, args...);
204         loader.load(parser);
205 }
206
207 /**
208 Loads an object from a file stored in a collection.  The object must havea
209 public Loader class.  Any extra arguments are passed to the Loader constructor.
210 */
211 template<typename T, typename C, typename... Args>
212 typename EnableIf<NeedsCollection<typename T::Loader>::value, void>::No load(T &obj, C &coll, const std::string &fn, Args &... args)
213 {
214         RefPtr<IO::Seekable> in = coll.open_raw(fn);
215         if(!in)
216                 throw IO::file_not_found(fn);
217
218         Parser parser(*in, fn);
219         typename T::Loader loader(obj, args...);
220         loader.load(parser);
221 }
222
223 #else
224
225 /**
226 Loads an object from a file.  The object must have a public Loader class.
227 */
228 template<typename T>
229 void load(T &obj, const std::string &fn)
230 {
231         IO::BufferedFile in(fn);
232
233         Parser parser(in, fn);
234         typename T::Loader loader(obj);
235         loader.load(parser);
236 }
237
238 /**
239 Loads an object from a file, passing one extra argument to the Loader
240 constructor.  The object must have a public Loader class.
241 */
242 template<typename T, typename U>
243 void load(T &obj, const std::string &fn, U &arg)
244 {
245         IO::BufferedFile in(fn);
246
247         Parser parser(in, fn);
248         typename T::Loader loader(obj, arg);
249         loader.load(parser);
250 }
251 #endif
252
253 } // namespace DataFile
254 } // namespace Msp
255
256 #endif