diff options
Diffstat (limited to 'project2/common/variables/lookup.cpp')
-rw-r--r-- | project2/common/variables/lookup.cpp | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/project2/common/variables/lookup.cpp b/project2/common/variables/lookup.cpp new file mode 100644 index 0000000..892968e --- /dev/null +++ b/project2/common/variables/lookup.cpp @@ -0,0 +1,74 @@ +#include <pch.hpp> +#include "../variables.h" +#include "../safeMapFind.h" +#include "../logger.h" +#include "../rowProcessor.h" +#include "../rowSet.h" +#include <boost/foreach.hpp> +#include "../scriptLoader.h" +#include "../scriptStorage.h" + + +/// Variable implementation that looks up it's value in a map of key(s)/value pairs +class VariableLookup : public VariableImplDyn, public RowProcessor { + private: + typedef std::vector<VariableType> Key; + typedef std::map<Key, VariableType> Map; + public: + class NotFound : public std::runtime_error { + public: + NotFound(const Key & k) : + std::runtime_error(mklist(k)) { + } + static std::string mklist(const Key & k) { + std::string l("("); + for (Key::const_iterator kp = k.begin(); kp != k.end(); ++kp) { + if (kp != k.begin()) l += ", "; + l += kp->operator const std::string &(); + } + l += ")"; + return l; + } + }; + VariableLookup(ScriptNodePtr e) : + VariableImplDyn(e), + RowProcessor(e), + name(e->value("name").as<Glib::ustring>()) + { + e->script->loader.addLoadTarget(e, Storer::into<ElementLoader>(&rowSets)); + } + VariableType value() const + { + if (map.empty()) { + fillCache(); + } + Key k; + k.reserve(parameters.size()); + BOOST_FOREACH(const Parameters::value_type & p, parameters) { + k.push_back(p.second); + } + return safeMapLookup<NotFound>(map, k); + } + private: + void fillCache() const + { + BOOST_FOREACH(const RowSets::value_type & rs, rowSets) { + rs->execute(filter, this); + } + Logger()->messagef(LOG_DEBUG, "%s: %s has filled cached with %zu items", + __PRETTY_FUNCTION__, name.c_str(), map.size()); + } + void rowReady(const RowState * rs) const + { + Key k; + BOOST_FOREACH(const Parameters::value_type & p, parameters) { + k.push_back(rs->getCurrentValue(p.first)); + } + map[k] = rs->getCurrentValue(name); + } + mutable Map map; + typedef ANONSTORAGEOF(RowSet) RowSets; + RowSets rowSets; + const Glib::ustring name; +}; +DECLARE_COMPONENT_LOADER("lookup", VariableLookup, VariableLoader); |