3 This file is part of libmspdatafile
4 Copyright © 2006 Mikko Rasa, Mikkosoft Productions
5 Distributed under the LGPL
7 #ifndef MSP_DATAFILE_LOADER_H_
8 #define MSP_DATAFILE_LOADER_H_
14 #include "statement.h"
26 virtual void execute(Loader &, const Statement &) const=0;
27 virtual ~LoaderAction() { }
33 class LoaderFunc0: public LoaderAction
36 typedef void (L::*FuncType)();
38 LoaderFunc0(FuncType f): func(f) { }
39 void execute(Loader &l, const Statement &st) const
41 if(st.args.size()!=0) throw TypeError(st.get_location()+": Wrong number of arguments");
42 (dynamic_cast<L &>(l).*func)();
48 template<typename L, typename A0>
49 class LoaderFunc1: public LoaderAction
52 typedef void (L::*FuncType)(A0);
54 LoaderFunc1(FuncType f): func(f) { }
55 void execute(Loader &l, const Statement &st) const
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>());
64 template<typename L, typename A0, typename A1>
65 class LoaderFunc2: public LoaderAction
68 typedef void (L::*FuncType)(A0, A1);
70 LoaderFunc2(FuncType f): func(f) { }
71 void execute(Loader &l, const Statement &st) const
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>());
80 template<typename L, typename A0, typename A1, typename A2>
81 class LoaderFunc3: public LoaderAction
84 typedef void (L::*FuncType)(A0, A1, A2);
86 LoaderFunc3(FuncType f): func(f) { }
87 void execute(Loader &l, const Statement &st) const
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>());
96 template<typename L, typename A0, typename A1, typename A2, typename A3>
97 class LoaderFunc4: public LoaderAction
100 typedef void (L::*FuncType)(A0, A1, A2, A3);
102 LoaderFunc4(FuncType f): func(f) { }
103 void execute(Loader &l, const Statement &st) const
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>());
112 template<typename L, typename T>
113 class LoadValue: public LoaderAction
116 typedef T L::*PointerType;
118 LoadValue(PointerType p): ptr(p) { }
119 void execute(Loader &l, const Statement &st) const
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>();
131 void load(const Statement &st)
133 for(std::list<Statement>::const_iterator i=st.sub.begin(); i!=st.sub.end(); ++i)
140 Statement st=p.parse();
147 for(ActionMap::iterator i=actions.begin(); i!=actions.end(); ++i)
151 Loader(): cur_st(0) { }
154 void add(const std::string &k, void (L::*func)())
155 { actions.insert(typename ActionMap::value_type(k, new LoaderFunc0<L>(func))); }
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))); }
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))); }
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))); }
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))); }
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))); }
177 void add(const std::string &k)
178 { actions.insert(ActionMap::value_type(k, 0)); }
182 { load_sub<S, typename S::Loader>(s); }
184 template<typename S, typename L>
188 throw Exception("load_sub called without current statement");
190 loader.load(*cur_st);
193 typedef std::map<std::string, LoaderAction *> ActionMap;
196 const Statement *cur_st;
198 void load_statement(const Statement &st)
201 ActionMap::iterator j=actions.find(st.keyword);
203 throw Exception(st.get_location()+": Unknown keyword '"+st.keyword+"'");
205 j->second->execute(*this, st);
211 void load(T &obj, const std::string &fn)
213 std::ifstream in(fn.c_str());
215 throw Exception("Couldn't open "+fn);
217 Parser parser(in, fn);
218 typename T::Loader loader(obj);
222 } // namespace DataFile