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