]> git.tdb.fi Git - libs/datafile.git/blob - source/loader.h
Loader design change
[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 Loader;
19 class Statement;
20
21 class LoaderAction
22 {
23 public:
24         virtual void execute(Loader &, const Statement &) const=0;
25         virtual ~LoaderAction() { }
26 protected:
27         LoaderAction() { }
28 };
29
30 template<typename L>
31 class LoaderFunc0: public LoaderAction
32 {
33 public:
34         typedef void (L::*FuncType)();
35         
36         LoaderFunc0(FuncType f): func(f) { }
37         void execute(Loader &l, const Statement &st) const
38         {
39                 if(st.args.size()!=0) throw TypeError("Wrong number of arguments");
40                 (dynamic_cast<L &>(l).*func)();
41         };
42 private:
43         FuncType func;
44 };
45
46 template<typename L, typename A0>
47 class LoaderFunc1: public LoaderAction
48 {
49 public:
50         typedef void (L::*FuncType)(A0);
51         
52         LoaderFunc1(FuncType f): func(f) { }
53         void execute(Loader &l, const Statement &st) const
54         {
55                 if(st.args.size()!=1) throw TypeError("Wrong number of arguments");
56                 (dynamic_cast<L &>(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
64 {
65 public:
66         typedef void (L::*FuncType)(A0, A1);
67         
68         LoaderFunc2(FuncType f): func(f) { }
69         void execute(Loader &l, const Statement &st) const
70         {
71                 if(st.args.size()!=2) throw TypeError("Wrong number of arguments");
72                 (dynamic_cast<L &>(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
80 {
81 public:
82         typedef void (L::*FuncType)(A0, A1, A2);
83         
84         LoaderFunc3(FuncType f): func(f) { }
85         void execute(Loader &l, const Statement &st) const
86         {
87                 if(st.args.size()!=3) throw TypeError("Wrong number of arguments");
88                 (dynamic_cast<L &>(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
96 {
97 public:
98         typedef void (L::*FuncType)(A0, A1, A2, A3);
99         
100         LoaderFunc4(FuncType f): func(f) { }
101         void execute(Loader &l, const Statement &st) const
102         {
103                 if(st.args.size()!=4) throw TypeError("Wrong number of arguments");
104                 (dynamic_cast<L &>(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
112 {
113 public:
114         typedef T L::*PointerType;
115         
116         LoadValue(PointerType p): ptr(p) { }
117         void execute(Loader &l, const Statement &st) const
118         {
119                 if(st.args.size()!=1) throw TypeError("Wrong number of arguments");
120                 dynamic_cast<typename L::Loader &>(l).get_object().*ptr=st.args[0].get<T>();
121         }
122 private:
123         PointerType ptr;
124 };
125
126 class Loader
127 {
128 public:
129         void load(const Statement &st)
130         {
131                 for(std::list<Statement>::const_iterator i=st.sub.begin(); i!=st.sub.end(); ++i)
132                         load_statement(*i);
133         }
134         void load(Parser &p)
135         {
136                 while(p)
137                 {
138                         Statement st=p.parse();
139                         if(st.valid)
140                                 load_statement(st);
141                 }
142         }
143         virtual ~Loader()
144         {
145                 for(ActionMap::iterator i=actions.begin(); i!=actions.end(); ++i)
146                         delete i->second;
147         }
148 protected:
149         Loader(): cur_st(0) { }
150         
151         template<typename L>
152         void add(const std::string &k, void (L::*func)())
153         { actions.insert(typename ActionMap::value_type(k, new LoaderFunc0<L>(func))); }
154         
155         template<typename L, typename A0>
156         void add(const std::string &k, void (L::*func)(A0))
157         { actions.insert(typename ActionMap::value_type(k, new LoaderFunc1<L, A0>(func))); }
158         
159         template<typename L, typename A0, typename A1>
160         void add(const std::string &k, void (L::*func)(A0, A1))
161         { actions.insert(typename ActionMap::value_type(k, new LoaderFunc2<L, A0, A1>(func))); }
162         
163         template<typename L, typename A0, typename A1, typename A2>
164         void add(const std::string &k, void (L::*func)(A0, A1, A2))
165         { actions.insert(typename ActionMap::value_type(k, new LoaderFunc3<L, A0, A1, A2>(func))); }
166         
167         template<typename L, typename A0, typename A1, typename A2, typename A3>
168         void add(const std::string &k, void (L::*func)(A0, A1, A2, A3))
169         { actions.insert(typename ActionMap::value_type(k, new LoaderFunc4<L, A0, A1, A2, A3>(func))); }
170
171         template<typename L, typename T>
172         void add(const std::string &k, T L::*p)
173         { actions.insert(typename ActionMap::value_type(k, new LoadValue<L, T>(p))); }
174
175         template<typename S>
176         void load_sub(S &s)
177         { load_sub<S, typename S::Loader>(s); }
178
179         template<typename S, typename L>
180         void load_sub(S &s)
181         {
182                 if(!cur_st)
183                         throw Exception("load_sub called without current statement");
184                 L loader(s);
185                 loader.load(*cur_st);
186         }
187 private:
188         typedef std::map<std::string, LoaderAction *> ActionMap;
189
190         ActionMap       actions;
191         const Statement *cur_st;
192
193         void load_statement(const Statement &st)
194         {
195                 cur_st=&st;
196                 ActionMap::iterator j=actions.find(st.keyword);
197                 if(j==actions.end())
198                         throw Exception(st.get_location()+": Unknown keyword '"+st.keyword+"'");
199                 j->second->execute(*this, st);
200                 cur_st=0;
201         }
202 };
203
204 } // namespace Parser
205 } // namespace Msp
206
207 #endif