1 #ifndef MSP_DATAFILE_LOADER_H_
2 #define MSP_DATAFILE_LOADER_H_
6 #include <msp/io/file.h>
7 #include "loaderaction.h"
9 #include "mspdatafile_api.h"
11 #include "statement.h"
17 Base class for data loaders. This class only provides core functionality.
18 You'll almost certainly want to use one of the BasicLoader classes instead.
20 Under normal circumstances, a class capable of being loaded should have a
21 nested typed called Loader which resolves to a descendant of this class. If
22 another structure is used, the loader object must be constructed manually.
24 A loader class should execute one or more calls to the various add() functions
25 to register actions with expected keywords. Currently possible actions are
26 calling a function of the loader, storing values in member variables of an
27 object and ignoring the statement. If a unexpected keyword is encountered, an
28 exception is thrown and the loading is aborted.
30 A sub-object can be loaded with one of the load_sub functions.
32 When loading has finished successfully, the virtual function finish() is
33 called. Any post-processing of the data should be placed here and not in the
36 See also classes ObjectLoader and CollectionObjectLoader in objectloader.h.
38 class MSPDATAFILE_API Loader: private NonCopyable
41 class MSPDATAFILE_API ActionMap: public std::map<StatementKey, LoaderAction *>, private NonCopyable
48 ActionMap local_actions;
49 ActionMap *actions = nullptr;
50 Parser *cur_parser = nullptr;
51 unsigned cur_level = 0;
52 const Statement *cur_st = nullptr;
53 bool sub_loaded = false;
55 std::vector<Loader *> aux_loaders;
57 bool check_sub_loads = false;
61 virtual ~Loader() = default;
63 /** Loads statements from a parser. */
67 /** Loads data from a statement. */
68 void load(const Statement &st);
70 /** Loads statemsnts from a parser, feeding them directly to actions. */
71 void load_direct(Parser &, unsigned);
73 /** Processes a single statement */
74 void load_statement(const Statement &st);
77 /** Loads a sub-object from the statement being processed. The Loader class
78 of the sub-object is automatically used. */
82 typename S::Loader ldr(s);
86 /** Loads a sub-object from the statement being processed with an extra
87 arguments for the Loader. The Loader class of the sub-object is
88 automatically used. */
89 template<typename S, typename... Args>
90 void load_sub(S &s, Args &&... args)
92 typename S::Loader ldr(s, std::forward<Args>(args)...);
96 /** Processes the current statement's substatements with another Loader. */
97 void load_sub_with(Loader &);
99 /** Sets the actions to be used when loading. If the map is empty,
100 init_actions will be called. */
101 void set_actions(ActionMap &);
102 virtual void init_actions() { }
104 /** Adds a keyword that is loaded by calling a function. */
106 void add(const std::string &k, void (L::*func)())
107 { add(k, new LoaderFunc0<L>(func)); }
109 template<typename L, typename A0>
110 void add(const std::string &k, void (L::*func)(A0))
111 { add(k, new LoaderFunc1<L, A0>(func)); }
113 template<typename L, typename... Args>
114 void add(const std::string &k, void (L::*func)(Args...))
115 { add(k, new LoaderFuncN<L, Args...>(func)); }
117 /** Adds a keyword that is loaded by calling a function with a bound
119 template<typename L, typename B0, typename... Args>
120 void add(const std::string &k, void (L::*func)(B0, Args...), const typename std::remove_reference<B0>::type &b0)
121 { add(k, new LoaderFuncNBound1<L, B0, Args...>(func, b0)); }
123 template<typename L, typename B0, typename... Args>
124 void add(const std::string &k, void (L::*func)(B0, Args...), B0 &&b0)
125 { add(k, new LoaderFuncNBound1<L, B0, Args...>(func, std::forward<B0>(b0))); }
127 /** Adds a keyword that is loaded into a member of the loaded object. */
128 template<typename L, typename T0>
129 void add(const std::string &k, T0 L::*p0)
130 { add(k, new LoadValue1<L, T0>(p0)); }
132 template<typename L, typename T0, typename T1>
133 void add(const std::string &k, T0 L::*p0, T1 L::*p1)
134 { add(k, new LoadValue2<L, T0, T1>(p0, p1)); }
136 /** Adds a keyword that is recognized but ignored. */
137 void add(const std::string &k)
141 void add(const std::string &, LoaderAction *);
144 void add_auxiliary_loader(Loader &);
147 bool has_action(const StatementKey &) const;
148 LoaderAction *find_action(const StatementKey &) const;
151 /** Returns the source of the statement being processed. This can be used
152 to implement relative paths in include-like statements. Note that the
153 source may not necessarily be a file. */
154 const std::string &get_source() const;
156 /** Returns the keyword of the statement being processed. Can be used to
157 implement dynamic keywords. */
158 const std::string &get_keyword() const;
160 virtual void finish() { }
165 Loads an object from a file. The object must have a public Loader class. Any
166 extra arguments are passed to the Loader constructor.
168 template<typename T, typename... Args>
169 void load(T &obj, const std::string &fn, Args &&... args)
171 IO::BufferedFile in(fn);
173 Parser parser(in, fn);
174 typename T::Loader loader(obj, std::forward<Args>(args)...);
179 Loads an object from a file stored in a collection. The object must have a
180 public Loader class. The collection is passed to the Loader constructor,
181 followed by any extra arguments.
183 template<typename T, typename... Args>
184 void load(T &obj, typename T::Loader::Collection &coll, const std::string &fn, Args &&... args)
186 RefPtr<IO::Seekable> in = coll.open_raw(fn);
188 throw IO::file_not_found(fn);
190 Parser parser(*in, fn);
191 typename T::Loader loader(obj, coll, std::forward<Args>(args)...);
196 Loads an object from a file stored in a collection. The object must have a
197 public Loader class. Any extra arguments are passed to the Loader constructor.
199 template<typename T, typename C, typename... Args>
200 typename std::enable_if<!NeedsCollection<typename T::Loader>::value>::type load(T &obj, C &coll, const std::string &fn, Args &&... args)
202 RefPtr<IO::Seekable> in = coll.open_raw(fn);
204 throw IO::file_not_found(fn);
206 Parser parser(*in, fn);
207 typename T::Loader loader(obj, std::forward<Args>(args)...);
211 } // namespace DataFile