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