X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Floader.h;h=5dac2e6b46fd8d35b38f35fafcc3f8cdb3549387;hb=HEAD;hp=604886125614728c2552d486decfa01afa19c804;hpb=011bd4dabaddc6c2739f14a427929bbb6191fea7;p=libs%2Fdatafile.git diff --git a/source/loader.h b/source/loader.h index 6048861..3fe26e7 100644 --- a/source/loader.h +++ b/source/loader.h @@ -1,9 +1,11 @@ #ifndef MSP_DATAFILE_LOADER_H_ #define MSP_DATAFILE_LOADER_H_ +#include #include #include #include "loaderaction.h" +#include "meta.h" #include "parser.h" #include "statement.h" @@ -32,30 +34,30 @@ destructor. See also classes ObjectLoader and CollectionObjectLoader in objectloader.h. */ -class Loader +class Loader: private NonCopyable { -private: - struct ActionKey +protected: + class ActionMap: public std::map, private NonCopyable { - std::string keyword; - std::string signature; - - ActionKey(const std::string &, const std::string &); - - bool operator<(const ActionKey &) const; + public: + ~ActionMap(); }; - typedef std::map ActionMap; - - ActionMap actions; - const Statement *cur_st; - bool sub_loaded; +private: + ActionMap local_actions; + ActionMap *actions = nullptr; + Parser *cur_parser = nullptr; + unsigned cur_level = 0; + const Statement *cur_st = nullptr; + bool sub_loaded = false; + bool direct = false; + std::vector aux_loaders; protected: - bool check_sub_loads; + bool check_sub_loads = false; - Loader(); + Loader() = default; public: - virtual ~Loader(); + virtual ~Loader() = default; /** Loads statements from a parser. */ void load(Parser &p); @@ -64,6 +66,9 @@ private: /** Loads data from a statement. */ void load(const Statement &st); + /** Loads statemsnts from a parser, feeding them directly to actions. */ + void load_direct(Parser &, unsigned); + /** Processes a single statement */ void load_statement(const Statement &st); @@ -78,18 +83,23 @@ protected: } /** Loads a sub-object from the statement being processed with an extra - parameter for the Loader. The Loader class of the sub-object is + arguments for the Loader. The Loader class of the sub-object is automatically used. */ - template - void load_sub(S &s, T &p) + template + void load_sub(S &s, Args &&... args) { - typename S::Loader ldr(s, p); + typename S::Loader ldr(s, std::forward(args)...); load_sub_with(ldr); } /** Processes the current statement's substatements with another Loader. */ void load_sub_with(Loader &); + /** Sets the actions to be used when loading. If the map is empty, + init_actions will be called. */ + void set_actions(ActionMap &); + virtual void init_actions() { } + /** Adds a keyword that is loaded by calling a function. */ template void add(const std::string &k, void (L::*func)()) @@ -99,21 +109,19 @@ protected: void add(const std::string &k, void (L::*func)(A0)) { add(k, new LoaderFunc1(func)); } - template - void add(const std::string &k, void (L::*func)(A0, A1)) - { add(k, new LoaderFunc2(func)); } - - template - void add(const std::string &k, void (L::*func)(A0, A1, A2)) - { add(k, new LoaderFunc3(func)); } + template + void add(const std::string &k, void (L::*func)(Args...)) + { add(k, new LoaderFuncN(func)); } - template - void add(const std::string &k, void (L::*func)(A0, A1, A2, A3)) - { add(k, new LoaderFunc4(func)); } + /** Adds a keyword that is loaded by calling a function with a bound + first argument. */ + template + void add(const std::string &k, void (L::*func)(B0, Args...), const typename std::remove_reference::type &b0) + { add(k, new LoaderFuncNBound1(func, b0)); } - template - void add(const std::string &k, void (L::*func)(A0, A1, A2, A3, A4)) - { add(k, new LoaderFunc5(func)); } + template + void add(const std::string &k, void (L::*func)(B0, Args...), B0 &&b0) + { add(k, new LoaderFuncNBound1(func, std::forward(b0))); } /** Adds a keyword that is loaded into a member of the loaded object. */ template @@ -126,12 +134,17 @@ protected: /** Adds a keyword that is recognized but ignored. */ void add(const std::string &k) - { add(k, 0); } + { add(k, nullptr); } private: void add(const std::string &, LoaderAction *); - LoaderAction *find_action(const ActionKey &) const; +protected: + void add_auxiliary_loader(Loader &); + +private: + bool has_action(const StatementKey &) const; + LoaderAction *find_action(const StatementKey &) const; protected: /** Returns the source of the statement being processed. This can be used @@ -139,30 +152,58 @@ protected: source may not necessarily be a file. */ const std::string &get_source() const; + /** Returns the keyword of the statement being processed. Can be used to + implement dynamic keywords. */ + const std::string &get_keyword() const; + virtual void finish() { } }; /** -Loads an object from a file. The object must have a public Loader class. +Loads an object from a file. The object must have a public Loader class. Any +extra arguments are passed to the Loader constructor. */ -template -void load(T &obj, const std::string &fn) +template +void load(T &obj, const std::string &fn, Args &&... args) { IO::BufferedFile in(fn); Parser parser(in, fn); - typename T::Loader loader(obj); + typename T::Loader loader(obj, std::forward(args)...); loader.load(parser); } -template -void load(T &obj, const std::string &fn, U &arg) +/** +Loads an object from a file stored in a collection. The object must have a +public Loader class. The collection is passed to the Loader constructor, +followed by any extra arguments. +*/ +template +void load(T &obj, typename T::Loader::Collection &coll, const std::string &fn, Args &&... args) { - IO::BufferedFile in(fn); + RefPtr in = coll.open_raw(fn); + if(!in) + throw IO::file_not_found(fn); - Parser parser(in, fn); - typename T::Loader loader(obj, arg); + Parser parser(*in, fn); + typename T::Loader loader(obj, coll, std::forward(args)...); + loader.load(parser); +} + +/** +Loads an object from a file stored in a collection. The object must have a +public Loader class. Any extra arguments are passed to the Loader constructor. +*/ +template +typename std::enable_if::value>::type load(T &obj, C &coll, const std::string &fn, Args &&... args) +{ + RefPtr in = coll.open_raw(fn); + if(!in) + throw IO::file_not_found(fn); + + Parser parser(*in, fn); + typename T::Loader loader(obj, std::forward(args)...); loader.load(parser); }