1 #ifndef MSP_DATAFILE_LOADER_H_
2 #define MSP_DATAFILE_LOADER_H_
5 #include <msp/io/file.h>
6 #include "loaderaction.h"
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.
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.
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.
28 A sub-object can be loaded with one of the load_sub functions.
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
34 See also classes ObjectLoader and CollectionObjectLoader in objectloader.h.
39 typedef std::map<StatementKey, LoaderAction *> ActionMap;
42 ActionMap local_actions;
46 const Statement *cur_st;
49 std::vector<Loader *> aux_loaders;
57 /** Loads statements from a parser. */
61 /** Loads data from a statement. */
62 void load(const Statement &st);
64 /** Loads statemsnts from a parser, feeding them directly to actions. */
65 void load_direct(Parser &, unsigned);
67 /** Processes a single statement */
68 void load_statement(const Statement &st);
71 /** Loads a sub-object from the statement being processed. The Loader class
72 of the sub-object is automatically used. */
76 typename S::Loader ldr(s);
80 /** Loads a sub-object from the statement being processed with an extra
81 parameter for the Loader. The Loader class of the sub-object is
82 automatically used. */
83 template<typename S, typename T>
84 void load_sub(S &s, T &p)
86 typename S::Loader ldr(s, p);
90 /** Processes the current statement's substatements with another Loader. */
91 void load_sub_with(Loader &);
93 /** Sets the actions to be used when loading. If the map is empty,
94 init_actions will be called. */
95 void set_actions(ActionMap &);
96 virtual void init_actions() { }
98 /** Adds a keyword that is loaded by calling a function. */
100 void add(const std::string &k, void (L::*func)())
101 { add(k, new LoaderFunc0<L>(func)); }
103 template<typename L, typename A0>
104 void add(const std::string &k, void (L::*func)(A0))
105 { add(k, new LoaderFunc1<L, A0>(func)); }
107 #if __cplusplus>=201103L
108 template<typename L, typename... Args>
109 void add(const std::string &k, void (L::*func)(Args...))
110 { add(k, new LoaderFuncN<L, Args...>(func)); }
113 template<typename L, typename A0, typename A1>
114 void add(const std::string &k, void (L::*func)(A0, A1))
115 { add(k, new LoaderFunc2<L, A0, A1>(func)); }
117 template<typename L, typename A0, typename A1, typename A2>
118 void add(const std::string &k, void (L::*func)(A0, A1, A2))
119 { add(k, new LoaderFunc3<L, A0, A1, A2>(func)); }
121 template<typename L, typename A0, typename A1, typename A2, typename A3>
122 void add(const std::string &k, void (L::*func)(A0, A1, A2, A3))
123 { add(k, new LoaderFunc4<L, A0, A1, A2, A3>(func)); }
125 template<typename L, typename A0, typename A1, typename A2, typename A3, typename A4>
126 void add(const std::string &k, void (L::*func)(A0, A1, A2, A3, A4))
127 { add(k, new LoaderFunc5<L, A0, A1, A2, A3, A4>(func)); }
130 #if __cplusplus>=201103L
131 /** Adds a keyword that is loaded by calling a function with a bound
133 template<typename L, typename B0, typename... Args>
134 void add(const std::string &k, void (L::*func)(B0, Args...), const typename RemoveReference<B0>::Type &b0)
135 { add(k, new LoaderFuncNBound1<L, B0, Args...>(func, b0)); }
138 /** Adds a keyword that is loaded into a member of the loaded object. */
139 template<typename L, typename T0>
140 void add(const std::string &k, T0 L::*p0)
141 { add(k, new LoadValue1<L, T0>(p0)); }
143 template<typename L, typename T0, typename T1>
144 void add(const std::string &k, T0 L::*p0, T1 L::*p1)
145 { add(k, new LoadValue2<L, T0, T1>(p0, p1)); }
147 /** Adds a keyword that is recognized but ignored. */
148 void add(const std::string &k)
152 void add(const std::string &, LoaderAction *);
155 void add_auxiliary_loader(Loader &);
158 bool has_action(const StatementKey &) const;
159 LoaderAction *find_action(const StatementKey &) const;
162 /** Returns the source of the statement being processed. This can be used
163 to implement relative paths in include-like statements. Note that the
164 source may not necessarily be a file. */
165 const std::string &get_source() const;
167 /** Returns the keyword of the statement being processed. Can be used to
168 implement dynamic keywords. */
169 const std::string &get_keyword() const;
171 virtual void finish() { }
175 #if __cplusplus>=201103L
177 Loads an object from a file. The object must have a public Loader class. Any
178 extra arguments are passed to the Loader constructor.
180 template<typename T, typename... Args>
181 void load(T &obj, const std::string &fn, Args &... args)
183 IO::BufferedFile in(fn);
185 Parser parser(in, fn);
186 typename T::Loader loader(obj, args...);
191 Loads an object from a file stored in a collection. The object must havea
192 public Loader class. The collection is passed to the Loader constructor,
193 followed by any extra arguments.
195 template<typename T, typename... Args>
196 void load(T &obj, typename T::Loader::Collection &coll, const std::string &fn, Args &... args)
198 RefPtr<IO::Seekable> in = coll.open_raw(fn);
200 throw IO::file_not_found(fn);
202 Parser parser(*in, fn);
203 typename T::Loader loader(obj, coll, args...);
208 Loads an object from a file stored in a collection. The object must havea
209 public Loader class. Any extra arguments are passed to the Loader constructor.
211 template<typename T, typename C, typename... Args>
212 typename EnableIf<NeedsCollection<typename T::Loader>::value, void>::No load(T &obj, C &coll, const std::string &fn, Args &... args)
214 RefPtr<IO::Seekable> in = coll.open_raw(fn);
216 throw IO::file_not_found(fn);
218 Parser parser(*in, fn);
219 typename T::Loader loader(obj, args...);
226 Loads an object from a file. The object must have a public Loader class.
229 void load(T &obj, const std::string &fn)
231 IO::BufferedFile in(fn);
233 Parser parser(in, fn);
234 typename T::Loader loader(obj);
239 Loads an object from a file, passing one extra argument to the Loader
240 constructor. The object must have a public Loader class.
242 template<typename T, typename U>
243 void load(T &obj, const std::string &fn, U &arg)
245 IO::BufferedFile in(fn);
247 Parser parser(in, fn);
248 typename T::Loader loader(obj, arg);
253 } // namespace DataFile