3 This file is part of libmspdatafile
4 Copyright © 2006-2008, 2010 Mikko Rasa, Mikkosoft Productions
5 Distributed under the LGPL
8 #ifndef MSP_DATAFILE_LOADER_H_
9 #define MSP_DATAFILE_LOADER_H_
12 #include <msp/io/buffered.h>
13 #include <msp/io/file.h>
15 #include "loaderaction.h"
17 #include "statement.h"
23 Base class for data loaders. This class only provides core functionality.
24 You'll almost certainly want to use one of the BasicLoader classes instead.
26 Under normal circumstances, a class capable of being loaded should have a
27 nested typed called Loader which resolves to a descendant of this class. If
28 another structure is used, the loader object must be constructed manually.
30 A loader class should execute one or more calls to the various add() functions
31 to register actions with expected keywords. Currently possible actions are
32 calling a function of the loader, storing values in member variables of an
33 object and ignoring the statement. If a unexpected keyword is encountered, an
34 exception is thrown and the loading is aborted.
36 A sub-object can be loaded with one of the load_sub functions.
38 When loading has finished successfully, the virtual function finish() is
39 called. Any post-processing of the data should be placed here and not in the
42 See also classes BasicLoader and BasicLoader2.
50 std::string signature;
52 ActionKey(const std::string &, const std::string &);
54 bool operator<(const ActionKey &) const;
57 typedef std::map<ActionKey, LoaderAction *> ActionMap;
60 const Statement *cur_st;
63 Loader(): cur_st(0) { }
67 /** Loads statements from a parser. */
71 /** Loads data from a statement. */
72 void load(const Statement &st);
74 /** Processes a single statement */
75 void load_statement(const Statement &st);
78 /** Loads a sub-object from the statement being processed. The Loader class
79 of the sub-object is automatically used. */
83 typename S::Loader ldr(s);
87 /** Loads a sub-object from the statement being processed with an extra
88 parameter for the Loader. The Loader class of the sub-object is
89 automatically used. */
90 template<typename S, typename T>
91 void load_sub(S &s, T &p)
93 typename S::Loader ldr(s, p);
97 /** Processes the current statement's substatements with another Loader. */
98 void load_sub_with(Loader &);
100 /** Adds a keyword that is loaded by calling a function. */
102 void add(const std::string &k, void (L::*func)())
103 { add(k, new LoaderFunc0<L>(func)); }
105 template<typename L, typename A0>
106 void add(const std::string &k, void (L::*func)(A0))
107 { add(k, new LoaderFunc1<L, A0>(func)); }
109 template<typename L, typename A0, typename A1>
110 void add(const std::string &k, void (L::*func)(A0, A1))
111 { add(k, new LoaderFunc2<L, A0, A1>(func)); }
113 template<typename L, typename A0, typename A1, typename A2>
114 void add(const std::string &k, void (L::*func)(A0, A1, A2))
115 { add(k, new LoaderFunc3<L, A0, A1, A2>(func)); }
117 template<typename L, typename A0, typename A1, typename A2, typename A3>
118 void add(const std::string &k, void (L::*func)(A0, A1, A2, A3))
119 { add(k, new LoaderFunc4<L, A0, A1, A2, A3>(func)); }
121 template<typename L, typename A0, typename A1, typename A2, typename A3, typename A4>
122 void add(const std::string &k, void (L::*func)(A0, A1, A2, A3, A4))
123 { add(k, new LoaderFunc5<L, A0, A1, A2, A3, A4>(func)); }
125 /** Adds a keyword that is loaded into a member of the loaded object. */
126 template<typename L, typename T0>
127 void add(const std::string &k, T0 L::*p0)
128 { add(k, new LoadValue1<L, T0>(p0)); }
130 template<typename L, typename T0, typename T1>
131 void add(const std::string &k, T0 L::*p0, T1 L::*p1)
132 { add(k, new LoadValue2<L, T0, T1>(p0, p1)); }
134 /** Adds a keyword that is recognized but ignored. */
135 void add(const std::string &k)
139 void add(const std::string &, LoaderAction *);
141 LoaderAction *find_action(const ActionKey &) const;
144 /** Returns the source of the statement being processed. This can be used
145 to implement relative paths in include-like statements. Note that the
146 source may not necessarily be a file. */
147 const std::string &get_source() const
150 throw InvalidState("get_source called without current statement");
151 return cur_st->source;
154 virtual void finish() { }
159 Provides the basic functionality of an object loader. Deriving from this
160 allows loading values directly into member variables of the objects.
163 class BasicLoader: public Loader
172 BasicLoader(O &o): obj(o) { }
173 O &get_object() const { return obj; }
178 Provides functionality for loading objects with a Collection. Deriving from
179 this allows loading pointers to objects in the collection automatically.
181 template<typename O, typename C>
182 class BasicLoader2: public BasicLoader<O>
185 typedef C Collection;
191 BasicLoader2(O &o, C &c): BasicLoader<O>(o), coll(c) { }
192 C &get_collection() const { return coll; }
197 Loads an object from a file. The object must have a public Loader class.
200 void load(T &obj, const std::string &fn)
203 IO::Buffered buf(in);
205 Parser parser(buf, fn);
206 typename T::Loader loader(obj);
210 template<typename T, typename U>
211 void load(T &obj, const std::string &fn, U &arg)
214 IO::Buffered buf(in);
216 Parser parser(buf, fn);
217 typename T::Loader loader(obj, arg);
221 } // namespace DataFile