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