1 #ifndef MSP_DATAFILE_LOADER_H_
2 #define MSP_DATAFILE_LOADER_H_
6 #include <msp/io/file.h>
7 #include "loaderaction.h"
10 #include "statement.h"
16 Base class for data loaders. This class only provides core functionality.
17 You'll almost certainly want to use one of the BasicLoader classes instead.
19 Under normal circumstances, a class capable of being loaded should have a
20 nested typed called Loader which resolves to a descendant of this class. If
21 another structure is used, the loader object must be constructed manually.
23 A loader class should execute one or more calls to the various add() functions
24 to register actions with expected keywords. Currently possible actions are
25 calling a function of the loader, storing values in member variables of an
26 object and ignoring the statement. If a unexpected keyword is encountered, an
27 exception is thrown and the loading is aborted.
29 A sub-object can be loaded with one of the load_sub functions.
31 When loading has finished successfully, the virtual function finish() is
32 called. Any post-processing of the data should be placed here and not in the
35 See also classes ObjectLoader and CollectionObjectLoader in objectloader.h.
37 class Loader: private NonCopyable
40 class ActionMap: public std::map<StatementKey, LoaderAction *>, private NonCopyable
47 ActionMap local_actions;
51 const Statement *cur_st;
54 std::vector<Loader *> aux_loaders;
62 /** Loads statements from a parser. */
66 /** Loads data from a statement. */
67 void load(const Statement &st);
69 /** Loads statemsnts from a parser, feeding them directly to actions. */
70 void load_direct(Parser &, unsigned);
72 /** Processes a single statement */
73 void load_statement(const Statement &st);
76 /** Loads a sub-object from the statement being processed. The Loader class
77 of the sub-object is automatically used. */
81 typename S::Loader ldr(s);
85 /** Loads a sub-object from the statement being processed with an extra
86 parameter for the Loader. The Loader class of the sub-object is
87 automatically used. */
88 template<typename S, typename T>
89 void load_sub(S &s, T &p)
91 typename S::Loader ldr(s, p);
95 /** Processes the current statement's substatements with another Loader. */
96 void load_sub_with(Loader &);
98 /** Sets the actions to be used when loading. If the map is empty,
99 init_actions will be called. */
100 void set_actions(ActionMap &);
101 virtual void init_actions() { }
103 /** Adds a keyword that is loaded by calling a function. */
105 void add(const std::string &k, void (L::*func)())
106 { add(k, new LoaderFunc0<L>(func)); }
108 template<typename L, typename A0>
109 void add(const std::string &k, void (L::*func)(A0))
110 { add(k, new LoaderFunc1<L, A0>(func)); }
112 template<typename L, typename... Args>
113 void add(const std::string &k, void (L::*func)(Args...))
114 { add(k, new LoaderFuncN<L, Args...>(func)); }
116 /** Adds a keyword that is loaded by calling a function with a bound
118 template<typename L, typename B0, typename... Args>
119 void add(const std::string &k, void (L::*func)(B0, Args...), const typename std::remove_reference<B0>::type &b0)
120 { add(k, new LoaderFuncNBound1<L, B0, Args...>(func, b0)); }
122 /** Adds a keyword that is loaded into a member of the loaded object. */
123 template<typename L, typename T0>
124 void add(const std::string &k, T0 L::*p0)
125 { add(k, new LoadValue1<L, T0>(p0)); }
127 template<typename L, typename T0, typename T1>
128 void add(const std::string &k, T0 L::*p0, T1 L::*p1)
129 { add(k, new LoadValue2<L, T0, T1>(p0, p1)); }
131 /** Adds a keyword that is recognized but ignored. */
132 void add(const std::string &k)
136 void add(const std::string &, LoaderAction *);
139 void add_auxiliary_loader(Loader &);
142 bool has_action(const StatementKey &) const;
143 LoaderAction *find_action(const StatementKey &) const;
146 /** Returns the source of the statement being processed. This can be used
147 to implement relative paths in include-like statements. Note that the
148 source may not necessarily be a file. */
149 const std::string &get_source() const;
151 /** Returns the keyword of the statement being processed. Can be used to
152 implement dynamic keywords. */
153 const std::string &get_keyword() const;
155 virtual void finish() { }
160 Loads an object from a file. The object must have a public Loader class. Any
161 extra arguments are passed to the Loader constructor.
163 template<typename T, typename... Args>
164 void load(T &obj, const std::string &fn, Args &... args)
166 IO::BufferedFile in(fn);
168 Parser parser(in, fn);
169 typename T::Loader loader(obj, args...);
174 Loads an object from a file stored in a collection. The object must have a
175 public Loader class. The collection is passed to the Loader constructor,
176 followed by any extra arguments.
178 template<typename T, typename... Args>
179 void load(T &obj, typename T::Loader::Collection &coll, const std::string &fn, Args &... args)
181 RefPtr<IO::Seekable> in = coll.open_raw(fn);
183 throw IO::file_not_found(fn);
185 Parser parser(*in, fn);
186 typename T::Loader loader(obj, coll, args...);
191 Loads an object from a file stored in a collection. The object must havea
192 public Loader class. Any extra arguments are passed to the Loader constructor.
194 template<typename T, typename C, typename... Args>
195 typename std::enable_if<!NeedsCollection<typename T::Loader>::value>::type load(T &obj, C &coll, const std::string &fn, Args &... args)
197 RefPtr<IO::Seekable> in = coll.open_raw(fn);
199 throw IO::file_not_found(fn);
201 Parser parser(*in, fn);
202 typename T::Loader loader(obj, args...);
206 } // namespace DataFile