]> git.tdb.fi Git - libs/datafile.git/blob - source/loader.h
Move LoaderActions to loaderaction.h
[libs/datafile.git] / source / loader.h
1 /* $Id$
2
3 This file is part of libmspdatafile
4 Copyright © 2006-2008  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 public:
47         /**
48         Loads data from a statement.  This is normally only used by the Loader class
49         itself for loading sub-items, but needs to be public so it can be accessed
50         in derived objects.
51         */
52         void load(const Statement &st);
53
54         /**
55         Loads statements from a parser.
56         */
57         void load(Parser &p);
58
59         virtual ~Loader();
60 protected:
61         Loader(): cur_st(0) { }
62
63         /**
64         Adds a keyword that is loaded with a zero-argument function.
65         */
66         template<typename L>
67         void add(const std::string &k, void (L::*func)())
68         { add(k, new LoaderFunc0<L>(func)); }
69
70         template<typename L, typename A0>
71         void add(const std::string &k, void (L::*func)(A0))
72         { add(k, new LoaderFunc1<L, A0>(func)); }
73
74         template<typename L, typename A0, typename A1>
75         void add(const std::string &k, void (L::*func)(A0, A1))
76         { add(k, new LoaderFunc2<L, A0, A1>(func)); }
77
78         template<typename L, typename A0, typename A1, typename A2>
79         void add(const std::string &k, void (L::*func)(A0, A1, A2))
80         { add(k, new LoaderFunc3<L, A0, A1, A2>(func)); }
81
82         template<typename L, typename A0, typename A1, typename A2, typename A3>
83         void add(const std::string &k, void (L::*func)(A0, A1, A2, A3))
84         { add(k, new LoaderFunc4<L, A0, A1, A2, A3>(func)); }
85
86         template<typename L, typename A0, typename A1, typename A2, typename A3, typename A4>
87         void add(const std::string &k, void (L::*func)(A0, A1, A2, A3, A4))
88         { add(k, new LoaderFunc5<L, A0, A1, A2, A3, A4>(func)); }
89
90         /**
91         Adds a keyword that is loaded into a variable of the loaded object.
92         */
93         template<typename L, typename T0>
94         void add(const std::string &k, T0 L::*p0)
95         { add(k, new LoadValue1<L, T0>(p0)); }
96
97         template<typename L, typename T0, typename T1>
98         void add(const std::string &k, T0 L::*p0, T1 L::*p1)
99         { add(k, new LoadValue2<L, T0, T1>(p0, p1)); }
100
101         /**
102         Adds a keyword that is recognized but ignored.
103         */
104         void add(const std::string &k)
105         { add(k, 0); }
106
107         /**
108         Loads a sub-object from the statement being processed.  The Loader class of
109         the sub-object is automatically used.
110         */
111         template<typename S>
112         void load_sub(S &s)
113         {
114                 typename S::Loader ldr(s);
115                 load_sub_with(ldr);
116         }
117
118         /**
119         Loads a sub-object from the statement being processed with an extra parameter
120         for the Loader.  The Loader class of the sub-object is automatically used.
121         */
122         template<typename S, typename T>
123         void load_sub(S &s, T &p)
124         {
125                 typename S::Loader ldr(s, p);
126                 load_sub_with(ldr);
127         }
128
129         /**
130         Processes the current statement's substatements with another Loader.
131         */
132         void load_sub_with(Loader &);
133
134         /**
135         Returns the source of the statement being processed.  This can be used to
136         implement relative paths in include-like statements.  Note that the source
137         may not necessarily be a file.
138         */
139         const std::string &get_source() const
140         {
141                 if(!cur_st)
142                         throw InvalidState("get_source called without current statement");
143                 return cur_st->source;
144         }
145
146         virtual void finish() { }
147 private:
148         typedef std::map<std::string, LoaderAction *> ActionMap;
149
150         ActionMap       actions;
151         const Statement *cur_st;
152
153         void add(const std::string &, LoaderAction *);
154         void load_statement(const Statement &st);
155 };
156
157
158 /**
159 Provides the basic functionality of an object loader.  Deriving from this
160 allows loading values directly into member variables of the objects.
161 */
162 template<typename O>
163 class BasicLoader: public Loader
164 {
165 public:
166         typedef O Object;
167
168 protected:
169         O &obj;
170
171 public:
172         BasicLoader(O &o): obj(o) { }
173         O &get_object() const { return obj; }
174 };
175
176
177 /**
178 Provides functionality for loading objects with a Collection.  Deriving from
179 this allows loading pointers to objects in the collection automatically.
180 */
181 template<typename O, typename C>
182 class BasicLoader2: public BasicLoader<O>
183 {
184 public:
185         typedef C Collection;
186
187 protected:
188         C &coll;
189
190 public:
191         BasicLoader2(O &o, C &c): BasicLoader<O>(o), coll(c) { }
192         C &get_collection() const { return coll; }
193 };
194
195
196 /**
197 Loads an object from a file.  The object must have a public Loader class.
198 */
199 template<typename T>
200 void load(T &obj, const std::string &fn)
201 {
202         IO::File in(fn);
203         IO::Buffered buf(in);
204
205         Parser parser(buf, fn);
206         typename T::Loader loader(obj);
207         loader.load(parser);
208 }
209
210 template<typename T, typename U>
211 void load(T &obj, const std::string &fn, U &arg)
212 {
213         IO::File in(fn);
214         IO::Buffered buf(in);
215
216         Parser parser(buf, fn);
217         typename T::Loader loader(obj, arg);
218         loader.load(parser);
219 }
220
221 } // namespace DataFile
222 } // namespace Msp
223
224 #endif