]> git.tdb.fi Git - libs/datafile.git/blob - source/loader.h
Add some optional (for now) extra checks for Loader
[libs/datafile.git] / source / loader.h
1 /* $Id$
2
3 This file is part of libmspdatafile
4 Copyright © 2006-2008, 2010  Mikko Rasa, Mikkosoft Productions
5 Distributed under the LGPL
6 */
7
8 #ifndef MSP_DATAFILE_LOADER_H_
9 #define MSP_DATAFILE_LOADER_H_
10
11 #include <map>
12 #include <msp/io/buffered.h>
13 #include <msp/io/file.h>
14 #include "except.h"
15 #include "loaderaction.h"
16 #include "parser.h"
17 #include "statement.h"
18
19 namespace Msp {
20 namespace DataFile {
21
22 /**
23 Base class for data loaders.  This class only provides core functionality.
24 You'll almost certainly want to use one of the BasicLoader classes instead.
25
26 Under normal circumstances, a class capable of being loaded should have a
27 nested typed called Loader which resolves to a descendant of this class.  If
28 another structure is used, the loader object must be constructed manually.
29
30 A loader class should execute one or more calls to the various add() functions
31 to register actions with expected keywords.  Currently possible actions are
32 calling a function of the loader, storing values in member variables of an
33 object and ignoring the statement.  If a unexpected keyword is encountered, an
34 exception is thrown and the loading is aborted.
35
36 A sub-object can be loaded with one of the load_sub functions.
37
38 When loading has finished successfully, the virtual function finish() is
39 called.  Any post-processing of the data should be placed here and not in the
40 destructor.
41
42 See also classes BasicLoader and BasicLoader2.
43 */
44 class Loader
45 {
46 private:
47         struct ActionKey
48         {
49                 std::string keyword;
50                 std::string signature;
51
52                 ActionKey(const std::string &, const std::string &);
53
54                 bool operator<(const ActionKey &) const;
55         };
56
57         typedef std::map<ActionKey, LoaderAction *> ActionMap;
58
59         ActionMap actions;
60         const Statement *cur_st;
61         bool sub_loaded;
62 protected:
63         bool allow_pointer_reload;
64         bool check_sub_loads;
65
66         Loader();
67 public:
68         virtual ~Loader();
69
70         bool is_pointer_reload_allowed() const { return allow_pointer_reload; }
71
72         /** Loads statements from a parser. */
73         void load(Parser &p);
74
75 private:
76         /** Loads data from a statement. */
77         void load(const Statement &st);
78
79         /** Processes a single statement */
80         void load_statement(const Statement &st);
81
82 protected:
83         /** Loads a sub-object from the statement being processed.  The Loader class
84         of the sub-object is automatically used. */
85         template<typename S>
86         void load_sub(S &s)
87         {
88                 typename S::Loader ldr(s);
89                 load_sub_with(ldr);
90         }
91
92         /** Loads a sub-object from the statement being processed with an extra
93         parameter for the Loader.  The Loader class of the sub-object is
94         automatically used. */
95         template<typename S, typename T>
96         void load_sub(S &s, T &p)
97         {
98                 typename S::Loader ldr(s, p);
99                 load_sub_with(ldr);
100         }
101
102         /** Processes the current statement's substatements with another Loader. */
103         void load_sub_with(Loader &);
104
105         /** Adds a keyword that is loaded by calling a function. */
106         template<typename L>
107         void add(const std::string &k, void (L::*func)())
108         { add(k, new LoaderFunc0<L>(func)); }
109
110         template<typename L, typename A0>
111         void add(const std::string &k, void (L::*func)(A0))
112         { add(k, new LoaderFunc1<L, A0>(func)); }
113
114         template<typename L, typename A0, typename A1>
115         void add(const std::string &k, void (L::*func)(A0, A1))
116         { add(k, new LoaderFunc2<L, A0, A1>(func)); }
117
118         template<typename L, typename A0, typename A1, typename A2>
119         void add(const std::string &k, void (L::*func)(A0, A1, A2))
120         { add(k, new LoaderFunc3<L, A0, A1, A2>(func)); }
121
122         template<typename L, typename A0, typename A1, typename A2, typename A3>
123         void add(const std::string &k, void (L::*func)(A0, A1, A2, A3))
124         { add(k, new LoaderFunc4<L, A0, A1, A2, A3>(func)); }
125
126         template<typename L, typename A0, typename A1, typename A2, typename A3, typename A4>
127         void add(const std::string &k, void (L::*func)(A0, A1, A2, A3, A4))
128         { add(k, new LoaderFunc5<L, A0, A1, A2, A3, A4>(func)); }
129
130         /** Adds a keyword that is loaded into a member of the loaded object. */
131         template<typename L, typename T0>
132         void add(const std::string &k, T0 L::*p0)
133         { add(k, new LoadValue1<L, T0>(p0)); }
134
135         template<typename L, typename T0, typename T1>
136         void add(const std::string &k, T0 L::*p0, T1 L::*p1)
137         { add(k, new LoadValue2<L, T0, T1>(p0, p1)); }
138
139         /** Adds a keyword that is recognized but ignored. */
140         void add(const std::string &k)
141         { add(k, 0); }
142
143 private:
144         void add(const std::string &, LoaderAction *);
145
146         LoaderAction *find_action(const ActionKey &) const;
147
148 protected:
149         /** Returns the source of the statement being processed.  This can be used
150         to implement relative paths in include-like statements.  Note that the
151         source may not necessarily be a file. */
152         const std::string &get_source() const
153         {
154                 if(!cur_st)
155                         throw InvalidState("get_source called without current statement");
156                 return cur_st->source;
157         }
158
159         virtual void finish() { }
160 };
161
162
163 /**
164 Deprecated.  See ObjectLoader in objectloader.h.
165 */
166 template<typename O>
167 class BasicLoader: public Loader
168 {
169 public:
170         typedef O Object;
171
172 protected:
173         O &obj;
174
175 public:
176         BasicLoader(O &o): obj(o) { }
177         O &get_object() const { return obj; }
178 };
179
180
181 /**
182 Deprecated.  See CollectionObjectLoader in objectloader.h.
183 */
184 template<typename O, typename C>
185 class BasicLoader2: public BasicLoader<O>
186 {
187 public:
188         typedef C Collection;
189
190 protected:
191         C &coll;
192
193 public:
194         BasicLoader2(O &o, C &c): BasicLoader<O>(o), coll(c) { }
195         C &get_collection() const { return coll; }
196 };
197
198
199 /**
200 Loads an object from a file.  The object must have a public Loader class.
201 */
202 template<typename T>
203 void load(T &obj, const std::string &fn)
204 {
205         IO::File in(fn);
206         IO::Buffered buf(in);
207
208         Parser parser(buf, fn);
209         typename T::Loader loader(obj);
210         loader.load(parser);
211 }
212
213 template<typename T, typename U>
214 void load(T &obj, const std::string &fn, U &arg)
215 {
216         IO::File in(fn);
217         IO::Buffered buf(in);
218
219         Parser parser(buf, fn);
220         typename T::Loader loader(obj, arg);
221         loader.load(parser);
222 }
223
224 } // namespace DataFile
225 } // namespace Msp
226
227 #endif