diff options
Diffstat (limited to 'project2/variables.cpp')
-rw-r--r-- | project2/variables.cpp | 209 |
1 files changed, 114 insertions, 95 deletions
diff --git a/project2/variables.cpp b/project2/variables.cpp index c8b2571..130d210 100644 --- a/project2/variables.cpp +++ b/project2/variables.cpp @@ -13,9 +13,35 @@ #include <boost/function.hpp> #include <boost/bind.hpp> +class UnknownVariableType : public std::exception { }; +class UnknownVariableSource : public std::exception { }; +class NoVariableDefinition : public std::exception { }; + +static +VariableType +makeVariableType(const Glib::ustring & src, const std::string & type, const std::string & format = std::string()) +{ + if (type == "stringptr" || type.empty()) return boost::shared_ptr<Glib::ustring>(new Glib::ustring(src)); + if (type == "string") return src; + if (type == "int") return boost::lexical_cast<int>(src); + if (type == "uint") return boost::lexical_cast<unsigned int>(src); + if (type == "lint") return boost::lexical_cast<long int>(src); + if (type == "luint") return boost::lexical_cast<long unsigned int>(src); + if (type == "llint") return boost::lexical_cast<long long int>(src); + if (type == "lluint") return boost::lexical_cast<long long unsigned int>(src); + if (type == "float") return boost::lexical_cast<float>(src); + if (type == "double") return boost::lexical_cast<double>(src); + if (type == "datetime") return boost::posix_time::time_from_string(src); + if (type == "datetimeptr") return boost::shared_ptr<boost::posix_time::ptime>(new boost::posix_time::ptime(boost::posix_time::time_from_string(src))); + throw UnknownVariableType(); +} + class VariableLiteral : public VariableImpl { public: - VariableLiteral(const Glib::ustring & src) : VariableImpl(src), val(src) { } + VariableLiteral(const Glib::ustring & src, const std::string & type = std::string()) : + val(makeVariableType(src, type)) + { + } virtual const VariableType & value() const { return val; } private: @@ -24,17 +50,31 @@ class VariableLiteral : public VariableImpl { class VariableImplDyn : public VariableImpl { public: - VariableImplDyn(const Glib::ustring & src) : VariableImpl(src), cacheValid(false) { } + VariableImplDyn(const xmlpp::Element * e) : + cacheValid(false) + { + try { + defaultValue = Variable(e, "default"); + } + catch (NoVariableDefinition) { + // That's cool... no default + } + } virtual const VariableType & value() const = 0; protected: mutable VariableType cache; mutable bool cacheValid; + boost::optional<Variable> defaultValue; }; class VariableSession : public VariableImplDyn { public: - VariableSession(const Glib::ustring & src) : VariableImplDyn(src) { } + VariableSession(const xmlpp::Element * e) : + VariableImplDyn(e), + name(e->get_attribute_value("name")) + { + } const VariableType & value() const { try { @@ -44,15 +84,21 @@ class VariableSession : public VariableImplDyn { if (!defaultValue) { throw; } - cache = *defaultValue; + cache = (*defaultValue)(); } return cache; } + private: + const Glib::ustring name; }; class VariableParam : public VariableImplDyn { public: - VariableParam(const Glib::ustring & src) : VariableImplDyn(src) { } + VariableParam(const xmlpp::Element * e) : + VariableImplDyn(e), + name(e->get_attribute_value("name")) + { + } const VariableType & value() const { if (!cacheValid) { @@ -63,33 +109,41 @@ class VariableParam : public VariableImplDyn { if (!defaultValue) { throw; } - cache = *defaultValue; + cache = (*defaultValue)(); } cacheValid = true; } return cache; } + private: + const Glib::ustring name; }; class VariableUri : public VariableImplDyn { public: - VariableUri(const Glib::ustring & src) : VariableImplDyn(src) { } + VariableUri(const xmlpp::Element * e) : + VariableImplDyn(e), + index(atoi(e->get_attribute_value("index").c_str())) + { + } const VariableType & value() const { if (!cacheValid) { try { - cache = ApplicationEngine::getCurrent()->env()->getParamUri(atoi(name.c_str())); + cache = ApplicationEngine::getCurrent()->env()->getParamUri(index); } catch (UriElementOutOfRange) { if (!defaultValue) { throw; } - cache = *defaultValue; + cache = (*defaultValue)(); } cacheValid = true; } return cache; } + private: + unsigned int index; }; static void assignHelper(VariableType & dest, const VariableType & src) { @@ -98,19 +152,21 @@ static void assignHelper(VariableType & dest, const VariableType & src) { class VariableParent : public VariableImplDyn, public RowUser { public: - VariableParent(const Glib::ustring & src, const RowUser * d) : - VariableImplDyn(src), + VariableParent(const xmlpp::Element * e, const RowUser * d) : + VariableImplDyn(e), row(NULL), - depth(src.find_first_not_of('^')), - attr(src[depth] == '!'), + depth(atoi(e->get_attribute_value("depth").c_str())), + attr(e->get_attribute("attribute")), + name(attr ? e->get_attribute_value("attribute") : e->get_attribute_value("name")), dep(d) { } - VariableParent(const Glib::ustring & name, unsigned int d) : - VariableImplDyn(name), + VariableParent(const Glib::ustring & n, bool a, unsigned int d) : + VariableImplDyn(NULL), row(NULL), depth(d), - attr(name[0] == '!'), + attr(a), + name(n), dep(NULL) { } @@ -146,13 +202,13 @@ class VariableParent : public VariableImplDyn, public RowUser { if (!defaultValue) { throw; } - cache = *defaultValue; + cache = (*defaultValue)(); } catch (RowSet::FieldDoesNotExist) { if (!defaultValue) { throw; } - cache = *defaultValue; + cache = (*defaultValue)(); } cacheValid = true; } @@ -177,57 +233,57 @@ class VariableParent : public VariableImplDyn, public RowUser { mutable ConstRowSetPtr row; const size_t depth; const bool attr; + const Glib::ustring name; const RowUser * dep; mutable boost::function2<void, VariableType &, ConstRowSetPtr> getValue; }; -class VariableParse : public VariableImplDyn, public RowUser { +class VariableFixed : public VariableImpl { public: - VariableParse(const Glib::ustring & src) : - VariableImplDyn(src) + VariableFixed(VariableType v) : + var(v) { - boost::tokenizer<boost::char_separator<char> > tokens(source.raw(), boost::char_separator<char>(" ")); - BOOST_FOREACH(std::string t, tokens) { - vars.push_back(Variable::create(t, this)); - } } const VariableType & value() const { - if (!cacheValid) { - Glib::ustring newCache; - BOOST_FOREACH(Variable::VariableImplPtr v, vars) { - if (newCache.length()) { - newCache.append(" "); - } - typedef Glib::ustring & (Glib::ustring::*appender)(const Glib::ustring &); - LexicalCall<Glib::ustring, Glib::ustring &>(boost::bind((appender)&Glib::ustring::append, newCache, _1), v->value()); - } - cache = newCache; - cacheValid = true; - } - return cache; - } - void rowChanged() const - { - cacheValid = false; + return var; } private: - std::list<Variable::VariableImplPtr> vars; + VariableType var; }; -Variable::Variable(const Glib::ustring & s) : - var(create(s)) -{ -} - -Variable::Variable(const xmlpp::Attribute * a) : - var(create(a->get_value())) -{ -} - -Variable::Variable(const xmlpp::Element * e) : - var(create(e->get_child_text()->get_content())) +Variable::Variable(const xmlpp::Element * e, const Glib::ustring & n, bool required, VariableType def) { + xmlpp::Attribute * a = e->get_attribute(n); + if (a) { + var = new VariableLiteral(a->get_value()); + return; + } + xmlpp::Element::NodeList cs = e->get_children(n); + if (cs.size() == 1) { + const xmlpp::Element * c = dynamic_cast<const xmlpp::Element *>(cs.front()); + if (c) { + Glib::ustring source = c->get_attribute_value("source"); + if (source == "session") + var = new VariableSession(c); + else if (source == "parent") + var = new VariableParent(c, NULL); + else if (source == "uri") + var = new VariableUri(c); + else if (source == "param") + var = new VariableParam(c); + else if (source == "literal" || source.empty()) + var = new VariableLiteral(c->get_attribute_value("value"), c->get_attribute_value("type")); + else + throw UnknownVariableSource(); + return; + } + } + if (!required) { + var = new VariableFixed(def); + return; + } + throw NoVariableDefinition(); } Variable::Variable(VariableImpl * v) : @@ -235,50 +291,13 @@ Variable::Variable(VariableImpl * v) : { } -Variable::VariableImplPtr -Variable::create(const Glib::ustring & s, RowUser * dep) +VariableImpl::~VariableImpl() { - if (s.empty()) { - return VariableImplPtr(new VariableLiteral(s)); - } - switch (s[0]) { - case '$': // param - return VariableImplPtr(new VariableParam(s)); - case '%': // session - return VariableImplPtr(new VariableSession(s)); - case '^': // parent - return VariableImplPtr(new VariableParent(s, dep)); - case '/': // uri - return VariableImplPtr(new VariableUri(s)); - case '*': // parser - return VariableImplPtr(new VariableParse(s.substr(1))); - case '=': // literal (explicit) - return VariableImplPtr(new VariableLiteral(s.substr(1))); - default: - return VariableImplPtr(new VariableLiteral(s)); - } } Variable -Variable::makeParent(const Glib::ustring & n, unsigned int d) -{ - return Variable(new VariableParent(n, d)); -} - -VariableImpl::VariableImpl(const Glib::ustring & src) : - source(src) -{ - Glib::ustring::const_iterator nameStart = std::find_if(source.begin(), source.end(), Glib::Unicode::isalnum); - Glib::ustring::const_iterator nameEnd = std::find(nameStart, source.end(), '|'); - name = Glib::ustring(nameStart, nameEnd); - Glib::ustring::const_iterator defaultStart = nameEnd; - if (defaultStart != source.end()) { - defaultStart++; - defaultValue = Glib::ustring(defaultStart, source.end()); - } -} - -VariableImpl::~VariableImpl() +Variable::makeParent(const Glib::ustring & name, bool attr, unsigned int dep) { + return Variable(new VariableParent(name, attr, dep)); } |