From 0881c95bef812d94d8086225c2736b4f15b4c8dc Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Sun, 19 Apr 2020 17:30:36 +0300 Subject: [PATCH] Support custom action maps in loader classes 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 | 42 ++++++++++++++++++++++++++++++++++-------- source/loader.h | 11 +++++++++-- 2 files changed, 43 insertions(+), 10 deletions(-) diff --git a/source/loader.cpp b/source/loader.cpp index 55492b6..51e22ed 100644 --- a/source/loader.cpp +++ b/source/loader.cpp @@ -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::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); diff --git a/source/loader.h b/source/loader.h index 7799a7e..5dac2e6 100644 --- a/source/loader.h +++ b/source/loader.h @@ -35,10 +35,12 @@ See also classes ObjectLoader and CollectionObjectLoader in objectloader.h. */ class Loader { -private: +protected: typedef std::map 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 void add(const std::string &k, void (L::*func)()) -- 2.43.0