]> git.tdb.fi Git - libs/datafile.git/commitdiff
Support custom action maps in loader classes
authorMikko Rasa <tdb@tdb.fi>
Sun, 19 Apr 2020 14:30:36 +0000 (17:30 +0300)
committerMikko Rasa <tdb@tdb.fi>
Sun, 19 Apr 2020 14:31:49 +0000 (17:31 +0300)
This makes it possible to implement a persistent action map which is
only initialized once the first time a particular class is used.

source/loader.cpp
source/loader.h

index 55492b66ce9dd04d3bed6ab211e990faafc9b6a3..51e22edf7a8e47c4ea1b02a3b1077d14e34f1f6e 100644 (file)
@@ -48,6 +48,7 @@ namespace Msp {
 namespace DataFile {
 
 Loader::Loader():
+       actions(0),
        cur_st(0),
        direct(false),
        check_sub_loads(false)
@@ -55,12 +56,15 @@ Loader::Loader():
 
 Loader::~Loader()
 {
-       for(ActionMap::iterator i=actions.begin(); i!=actions.end(); ++i)
+       for(ActionMap::iterator i=local_actions.begin(); i!=local_actions.end(); ++i)
                delete i->second;
 }
 
 void Loader::load(Parser &p)
 {
+       if(!actions)
+               throw logic_error("no actions");
+
        while(p)
        {
                if(p.peek(0))
@@ -78,6 +82,9 @@ void Loader::load(Parser &p)
 
 void Loader::load(const Statement &st)
 {
+       if(!actions)
+               throw logic_error("no actions");
+
        for(list<Statement>::const_iterator i=st.sub.begin(); i!=st.sub.end(); ++i)
                load_statement(*i);
        finish();
@@ -156,17 +163,30 @@ void Loader::load_sub_with(Loader &ldr)
                throw logic_error("no current statement");
 }
 
+void Loader::set_actions(ActionMap &a)
+{
+       if(actions)
+               throw logic_error("actions already set");
+
+       actions = &a;
+       if(a.empty())
+               init_actions();
+}
+
 void Loader::add(const string &kwd, LoaderAction *act)
 {
+       if(!actions)
+               actions = &local_actions;
+
        StatementKey key(kwd, (act ? act->get_signature() : "*"));
-       ActionMap::iterator i = actions.find(key);
-       if(i!=actions.end())
+       ActionMap::iterator i = actions->find(key);
+       if(i!=actions->end())
        {
                delete i->second;
                i->second = act;
        }
        else
-               actions[key] = act;
+               (*actions)[key] = act;
 }
 
 void Loader::add_auxiliary_loader(Loader &ldr)
@@ -176,8 +196,11 @@ void Loader::add_auxiliary_loader(Loader &ldr)
 
 bool Loader::has_action(const StatementKey &key) const
 {
-       ActionMap::const_iterator i = actions.lower_bound(StatementKey(key.keyword, string()));
-       for(; (i!=actions.end() && i->first.keyword==key.keyword); ++i)
+       if(!actions)
+               return false;
+
+       ActionMap::const_iterator i = actions->lower_bound(StatementKey(key.keyword, string()));
+       for(; (i!=actions->end() && i->first.keyword==key.keyword); ++i)
                if(signature_match(key.signature, i->first.signature))
                        return true;
        return false;
@@ -185,8 +208,11 @@ bool Loader::has_action(const StatementKey &key) const
 
 LoaderAction *Loader::find_action(const StatementKey &key) const
 {
-       ActionMap::const_iterator begin = actions.lower_bound(StatementKey(key.keyword, string()));
-       ActionMap::const_iterator end = actions.upper_bound(StatementKey(key.keyword, "~"));
+       if(!actions)
+               return 0;
+
+       ActionMap::const_iterator begin = actions->lower_bound(StatementKey(key.keyword, string()));
+       ActionMap::const_iterator end = actions->upper_bound(StatementKey(key.keyword, "~"));
 
        if(begin==end)
                throw unknown_keyword(key.keyword);
index 7799a7eacb5dd404915f25cbfe87f0665f515436..5dac2e6b46fd8d35b38f35fafcc3f8cdb3549387 100644 (file)
@@ -35,10 +35,12 @@ See also classes ObjectLoader and CollectionObjectLoader in objectloader.h.
 */
 class Loader
 {
-private:
+protected:
        typedef std::map<StatementKey, LoaderAction *> ActionMap;
 
-       ActionMap actions;
+private:
+       ActionMap local_actions;
+       ActionMap *actions;
        Parser *cur_parser;
        unsigned cur_level;
        const Statement *cur_st;
@@ -88,6 +90,11 @@ protected:
        /** 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<typename L>
        void add(const std::string &k, void (L::*func)())