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