]> git.tdb.fi Git - libs/datafile.git/blob - source/loader.h
Add files
[libs/datafile.git] / source / loader.h
1 /*
2 This file is part of libmspparser
3 Copyright © 2006 Mikko Rasa, Mikkosoft Productions
4 Distributed under the LGPL
5 */
6 #ifndef MSP_PARSER_LOADER_H_
7 #define MSP_PARSER_LOADER_H_
8
9 #include <map>
10 #include <msp/error.h>
11 #include "parser.h"
12 #include "statement.h"
13 #include "value.h"
14
15 namespace Msp {
16 namespace Parser {
17
18 class Statement;
19
20 template<typename L>
21 class LoaderAction
22 {
23 public:
24         virtual void execute(L &, const Statement &) const=0;
25         virtual ~LoaderAction() { }
26 protected:
27         LoaderAction() { }
28 };
29
30 template<typename L>
31 class LoaderFunc0: public LoaderAction<L>
32 {
33 public:
34         typedef void (L::*FuncType)();
35         
36         LoaderFunc0(FuncType f): func(f) { }
37         void execute(L &l, const Statement &st) const
38         {
39                 if(st.args.size()!=0) throw TypeError("Wrong number of arguments");
40                 (l.*func)();
41         };
42 private:
43         FuncType func;
44 };
45
46 template<typename L, typename A0>
47 class LoaderFunc1: public LoaderAction<L>
48 {
49 public:
50         typedef void (L::*FuncType)(A0);
51         
52         LoaderFunc1(FuncType f): func(f) { }
53         void execute(L &l, const Statement &st) const
54         {
55                 if(st.args.size()!=1) throw TypeError("Wrong number of arguments");
56                 (l.*func)(st.args[0].get<A0>());
57         }
58 private:
59         FuncType func;
60 };
61
62 template<typename L, typename A0, typename A1>
63 class LoaderFunc2: public LoaderAction<L>
64 {
65 public:
66         typedef void (L::*FuncType)(A0, A1);
67         
68         LoaderFunc2(FuncType f): func(f) { }
69         void execute(L &l, const Statement &st) const
70         {
71                 if(st.args.size()!=2) throw TypeError("Wrong number of arguments");
72                 (l.*func)(st.args[0].get<A0>(), st.args[1].get<A1>());
73         }
74 private:
75         FuncType func;
76 };
77
78 template<typename L, typename A0, typename A1, typename A2>
79 class LoaderFunc3: public LoaderAction<L>
80 {
81 public:
82         typedef void (L::*FuncType)(A0, A1, A2);
83         
84         LoaderFunc3(FuncType f): func(f) { }
85         void execute(L &l, const Statement &st) const
86         {
87                 if(st.args.size()!=3) throw TypeError("Wrong number of arguments");
88                 (l.*func)(st.args[0].get<A0>(), st.args[1].get<A1>(), st.args[2].get<A2>());
89         }
90 private:
91         FuncType func;
92 };
93
94 template<typename L, typename A0, typename A1, typename A2, typename A3>
95 class LoaderFunc4: public LoaderAction<L>
96 {
97 public:
98         typedef void (L::*FuncType)(A0, A1, A2, A3);
99         
100         LoaderFunc4(FuncType f): func(f) { }
101         void execute(L &l, const Statement &st) const
102         {
103                 if(st.args.size()!=4) throw TypeError("Wrong number of arguments");
104                 (l.*func)(st.args[0].get<A0>(), st.args[1].get<A1>(), st.args[2].get<A2>(), st.args[3].get<A3>());
105         }
106 private:
107         FuncType func;
108 };
109
110 template<typename L, typename T>
111 class LoadValue: public LoaderAction<L>
112 {
113 public:
114         typedef T L::ObjectType::*PointerType;
115         
116         LoadValue(PointerType p): ptr(p) { }
117         void execute(L &l, const Statement &st) const
118         {
119                 if(st.args.size()!=1) throw TypeError("Wrong number of arguments");
120                 l.get_object().*ptr=st.args[0].get<T>();
121         }
122 private:
123         PointerType ptr;
124 };
125
126 template<typename L, typename S>
127 class SubLoader0: public LoaderAction<L>
128 {
129 public:
130         typedef typename S::ObjectType &(L::*FuncType)();
131
132         SubLoader0(FuncType f): func(f) { }
133         void execute(L &l, const Statement &st) const
134         {
135                 if(st.args.size()!=0) throw TypeError("Wrong number of arguments");
136                 typename S::ObjectType &obj=(l.*func)();
137                 S sl(obj);
138                 sl.load(st);
139         }
140 private:
141         FuncType func;
142 };
143
144 template<typename L, typename S, typename A0>
145 class SubLoader1: public LoaderAction<L>
146 {
147 public:
148         typedef typename S::ObjectType &(L::*FuncType)(A0);
149
150         SubLoader1(FuncType f): func(f) { }
151         void execute(L &l, const Statement &st) const
152         {
153                 if(st.args.size()!=1) throw TypeError("Wrong number of arguments");
154                 typename S::ObjectType &obj=(l.*func)(st.args[0].get<A0>());
155                 S sl(obj);
156                 sl.load(st);
157         }
158 private:
159         FuncType func;
160 };
161
162 template<typename C, typename L>
163 class Loader
164 {
165 public:
166         typedef C ObjectType;
167         
168         C &get_object() { return obj; }
169         void load(const Statement &st)
170         {
171                 for(std::list<Statement>::const_iterator i=st.sub.begin(); i!=st.sub.end(); ++i)
172                         load_statement(*i);
173         }
174         void load(Parser &p)
175         {
176                 while(p)
177                 {
178                         Statement st=p.parse();
179                         if(st.valid)
180                                 load_statement(st);
181                 }
182         }
183         virtual ~Loader()
184         {
185                 for(typename ActionMap::iterator i=actions.begin(); i!=actions.end(); ++i)
186                         delete i->second;
187         }
188 protected:
189         typedef std::map<std::string, LoaderAction<L > *> ActionMap;
190
191         C &obj;
192         
193         Loader(C &o): obj(o) { }
194         
195         void add(const std::string &k, void (L::*func)())
196         { actions.insert(typename ActionMap::value_type(k, new LoaderFunc0<L>(func))); }
197         
198         template<typename A0>
199         void add(const std::string &k, void (L::*func)(A0))
200         { actions.insert(typename ActionMap::value_type(k, new LoaderFunc1<L, A0>(func))); }
201         
202         template<typename A0, typename A1>
203         void add(const std::string &k, void (L::*func)(A0, A1))
204         { actions.insert(typename ActionMap::value_type(k, new LoaderFunc2<L, A0, A1>(func))); }
205         
206         template<typename A0, typename A1, typename A2>
207         void add(const std::string &k, void (L::*func)(A0, A1, A2))
208         { actions.insert(typename ActionMap::value_type(k, new LoaderFunc3<L, A0, A1, A2>(func))); }
209         
210         template<typename A0, typename A1, typename A2, typename A3>
211         void add(const std::string &k, void (L::*func)(A0, A1, A2, A3))
212         { actions.insert(typename ActionMap::value_type(k, new LoaderFunc4<L, A0, A1, A2, A3>(func))); }
213
214         template<typename S>
215         void add(const std::string &k, typename S::ObjectType &(L::*func)())
216         { actions.insert(typename ActionMap::value_type(k, new SubLoader0<L, S>(func))); }
217
218         template<typename S, typename A0>
219         void add(const std::string &k, typename S::ObjectType &(L::*func)(A0))
220         { actions.insert(typename ActionMap::value_type(k, new SubLoader1<L, S, A0>(func))); }
221
222         template<typename T>
223         void add(const std::string &k, T C::*p)
224         { actions.insert(typename ActionMap::value_type(k, new LoadValue<L, T>(p))); }
225 private:
226         ActionMap actions;
227
228         void load_statement(const Statement &st)
229         {
230                 typename ActionMap::iterator j=actions.find(st.keyword);
231                 if(j==actions.end())
232                         throw Exception(st.get_location()+": Unknown keyword '"+st.keyword+"'");
233                 j->second->execute(dynamic_cast<L &>(*this), st);
234         }
235 };
236
237 } // namespace Parser
238 } // namespace Msp
239
240 #endif