diff options
author | randomdan <randomdan@localhost> | 2011-02-01 21:13:39 +0000 |
---|---|---|
committer | randomdan <randomdan@localhost> | 2011-02-01 21:13:39 +0000 |
commit | 1afa0dc6e323edea0e55594cf11c9536cffab75f (patch) | |
tree | 026a2c3aac2748f089406f260b81499125da69ed | |
parent | Call curl global cleanup when finished (diff) | |
download | project2-1afa0dc6e323edea0e55594cf11c9536cffab75f.tar.bz2 project2-1afa0dc6e323edea0e55594cf11c9536cffab75f.tar.xz project2-1afa0dc6e323edea0e55594cf11c9536cffab75f.zip |
Add lots of funky stuff to make the system (internally) type safe
36 files changed, 428 insertions, 125 deletions
diff --git a/project2/console/consoleAppEngine.cpp b/project2/console/consoleAppEngine.cpp index 908c1a1..bd17458 100644 --- a/project2/console/consoleAppEngine.cpp +++ b/project2/console/consoleAppEngine.cpp @@ -13,7 +13,7 @@ class ConsoleSession : public Session { { } - virtual Glib::ustring GetValue(const Glib::ustring & name) const + virtual const VariableType & GetValue(const Glib::ustring & name) const { Values::const_iterator i = vars.find(name); if (i == vars.end()) { @@ -25,7 +25,7 @@ class ConsoleSession : public Session { { return vars; } - virtual void SetValue(const Glib::ustring & name, const Glib::ustring & value) + virtual void SetValue(const Glib::ustring & name, const VariableType & value) { vars[name] = value; } diff --git a/project2/dumpTask.cpp b/project2/dumpTask.cpp index caf3c86..e424dfc 100644 --- a/project2/dumpTask.cpp +++ b/project2/dumpTask.cpp @@ -21,18 +21,59 @@ DumpTask::loadComplete(const CommonObjects *) { } +class Printer : public boost::static_visitor<> { + public: + void operator()(const long long int & i) const { + fprintf(stderr, "%lld", i); + } + void operator()(const long int & i) const { + fprintf(stderr, "%ld", i); + } + void operator()(const int & i) const { + fprintf(stderr, "%d", i); + } + void operator()(const short int & i) const { + fprintf(stderr, "%hd", i); + } + void operator()(const long long unsigned int & i) const { + fprintf(stderr, "%llu", i); + } + void operator()(const long unsigned int & i) const { + fprintf(stderr, "%lu", i); + } + void operator()(const unsigned int & i) const { + fprintf(stderr, "%u", i); + } + void operator()(const short unsigned int & i) const { + fprintf(stderr, "%hu", i); + } + void operator()(const float & i) const { + fprintf(stderr, "%g", i); + } + void operator()(const double & i) const { + fprintf(stderr, "%g", i); + } + void operator()(const Glib::ustring & i) const { + fprintf(stderr, "'%s'", i.c_str()); + } + void operator()(const boost::shared_ptr<const Glib::ustring> & i) const { + fprintf(stderr, "'%s'", i->c_str()); + } +}; + void DumpTask::execute() const { const RowSet::RowValuesStack::value_type & r = *++RowSet::Stack().rbegin(); unsigned int cols = r->columnCount(); + Printer printer; for (unsigned int c = 0; c < cols; c += 1) { if (c > 0) { fprintf(stderr, ", "); } fprintf(stderr, "%s = ", r->getColumnName(c).c_str()); if (!r->isNull(c)) { - fprintf(stderr, "'%s'", r->getCurrentValue(c).c_str()); + boost::apply_visitor<const Printer, const VariableType>(printer, r->getCurrentValue(c)); } } fprintf(stderr, "\n"); diff --git a/project2/fileRows.cpp b/project2/fileRows.cpp index 600ab7c..28de335 100644 --- a/project2/fileRows.cpp +++ b/project2/fileRows.cpp @@ -2,6 +2,7 @@ #include "rowProcessor.h" #include "xmlObjectLoader.h" #include "exceptions.h" +#include "genericVisitor.h" #include <boost/algorithm/string/predicate.hpp> ElementLoaderImpl<FileRows> filerowsLoader("filerows"); @@ -117,10 +118,10 @@ FileRows::execute(const RowProcessor * rp) const } } -const Glib::ustring & +VariableType FileRows::getCurrentValue(unsigned int col) const { - return *values[col]; + return values[col]; } bool @@ -135,13 +136,13 @@ FileRows::isNull(const Glib::ustring & col) const return false; } -const Glib::ustring & +VariableType FileRows::getCurrentValue(const Glib::ustring & id) const { Values::const_iterator v = values.begin(); for (Columns::const_iterator i = columns.begin(); i != columns.end(); i++, v++) { if (*i == id) { - return **v; + return *v; } } throw RowSet::FieldDoesNotExist(); @@ -165,7 +166,7 @@ FileRows::addColumn(const Glib::ustring & rawtok) const FileStarChannel FileRows::doOpen() const { - FILE * f = fopen(path->c_str(), "r"); + FILE * f = LexicalCall<const char *, FILE *>(boost::bind(&popen, _1, "r"), path()); if (!f) { throw FileNotReadable(); } diff --git a/project2/fileRows.h b/project2/fileRows.h index 3ed9211..0c5e3ce 100644 --- a/project2/fileRows.h +++ b/project2/fileRows.h @@ -21,8 +21,8 @@ class FileRows : public RowSet { virtual void setFilter(const Glib::ustring &); unsigned int columnCount() const; const Glib::ustring & getColumnName(unsigned int col) const; - const Glib::ustring & getCurrentValue(const Glib::ustring & id) const; - const Glib::ustring & getCurrentValue(unsigned int col) const; + VariableType getCurrentValue(const Glib::ustring & id) const; + VariableType getCurrentValue(unsigned int col) const; bool isNull(unsigned int col) const; bool isNull(const Glib::ustring & id) const; diff --git a/project2/fsRows.cpp b/project2/fsRows.cpp index 2ee72ac..5d62d38 100644 --- a/project2/fsRows.cpp +++ b/project2/fsRows.cpp @@ -2,6 +2,7 @@ #include "xmlObjectLoader.h" #include "rowProcessor.h" #include "exceptions.h" +#include "genericVisitor.h" #include <boost/filesystem/operations.hpp> #include <boost/algorithm/string/predicate.hpp> #include <boost/algorithm/string/split.hpp> @@ -139,12 +140,15 @@ FsRows::execute(const RowProcessor * rp) const { rowNum = 1; depth = 0; - fsRoot = rp->getParameter("root"); + fsRoot = boost::lexical_cast<boost::filesystem::path>(rp->getParameter("root")); // Ensure there is a trailing / fsRoot = (fsRoot / ".").remove_filename(); specs.clear(); SpecSpec s; - boost::algorithm::split(s, rp->getParameter("spec"), Glib::Unicode::isspace, boost::algorithm::token_compress_on); + typedef SpecSpec & (*splitter)(SpecSpec &, const Glib::ustring &, bool (*)(gunichar), boost::algorithm::token_compress_mode_type); + splitter split = &boost::algorithm::split; + LexicalCall<Glib::ustring, void>(boost::bind(split, boost::ref(s), _1, Glib::Unicode::isspace, boost::algorithm::token_compress_on), + rp->getParameter("spec")); for (SpecSpec::const_iterator sf = s.begin(); sf != s.end(); ) { const Glib::ustring & name = (*sf++); if (name == "-name") { @@ -206,13 +210,13 @@ FsRows::isNull(const Glib::ustring &) const return false; } -const Glib::ustring & +VariableType FsRows::getCurrentValue(const Glib::ustring &) const { return curPathStr; } -const Glib::ustring & +VariableType FsRows::getCurrentValue(unsigned int) const { return curPathStr; diff --git a/project2/fsRows.h b/project2/fsRows.h index 7e8c3ce..a93619f 100644 --- a/project2/fsRows.h +++ b/project2/fsRows.h @@ -34,8 +34,8 @@ class FsRows : public RowSet { virtual void setFilter(const Glib::ustring &); unsigned int columnCount() const; const Glib::ustring & getColumnName(unsigned int col) const; - const Glib::ustring & getCurrentValue(const Glib::ustring & id) const; - const Glib::ustring & getCurrentValue(unsigned int col) const; + VariableType getCurrentValue(const Glib::ustring & id) const; + VariableType getCurrentValue(unsigned int col) const; bool isNull(unsigned int col) const; bool isNull(const Glib::ustring & id) const; virtual RowAttribute resolveAttr(const Glib::ustring & attrName) const; diff --git a/project2/genericVisitor.h b/project2/genericVisitor.h new file mode 100644 index 0000000..be9b462 --- /dev/null +++ b/project2/genericVisitor.h @@ -0,0 +1,129 @@ +#ifndef GENERIC_VISITOR_H +#define GENERIC_VISITOR_H + +#include <boost/lexical_cast.hpp> +#include <boost/function.hpp> +#include <boost/bind.hpp> + +namespace LexicalVisitorHelper { + template <typename T, typename S, typename R> + class lexical_run { + public: + R operator()(const boost::function1<R, T> & func, const S & i) const + { + return func(boost::lexical_cast<T>(i)); + } + }; + template <typename T, typename R> + class lexical_run<T, T, R> { + public: + R operator()(const boost::function1<R, T> & func, const T & i) const + { + return func(i); + } + }; + template <typename S, typename R> + class lexical_run<const unsigned char *, S, R> { + public: + R operator()(const boost::function1<R, const unsigned char *> & func, const S & i) const + { + return func(reinterpret_cast<const unsigned char *>(boost::lexical_cast<Glib::ustring>(i).c_str())); + } + }; + template <typename S, typename R> + class lexical_run<const char *, S, R> { + public: + R operator()(const boost::function1<R, const char *> & func, const S & i) const + { + return func(boost::lexical_cast<Glib::ustring>(i).c_str()); + } + }; + template <typename R> + class lexical_run<const unsigned char *, Glib::ustring, R> { + public: + R operator()(const boost::function1<R, const unsigned char *> & func, const Glib::ustring & i) const + { + return func(reinterpret_cast<const unsigned char *>(i.c_str())); + } + }; + template <typename R> + class lexical_run<const char *, Glib::ustring, R> { + public: + R operator()(const boost::function1<R, const char *> & func, const Glib::ustring & i) const + { + return func(i.c_str()); + } + }; + template <typename T, typename R> + class lexical_run<T, const T *, R> { + public: + R operator()(const boost::function1<R, T> & func, const T * i) const + { + return func(*i); + } + }; + template <typename R> + class lexical_run<const unsigned char *, const Glib::ustring *, R> { + public: + R operator()(const boost::function1<R, const unsigned char *> & func, const Glib::ustring * i) const + { + return func(reinterpret_cast<const unsigned char *>(i->c_str())); + } + }; + template <typename R> + class lexical_run<const char *, const Glib::ustring *, R> { + public: + R operator()(const boost::function1<R, const char *> & func, const Glib::ustring * i) const + { + return func(i->c_str()); + } + }; + template <typename T, typename R> + class lexical_run<T, boost::shared_ptr<const T>, R> { + public: + R operator()(const boost::function1<R, T> & func, const boost::shared_ptr<const T> & i) const + { + return func(*i); + } + }; + template <typename R> + class lexical_run<const char *, boost::shared_ptr<const Glib::ustring>, R> { + public: + R operator()(const boost::function1<R, const char *> & func, const boost::shared_ptr<const Glib::ustring> & i) const + { + return func(i->c_str()); + } + }; + template <typename R> + class lexical_run<const unsigned char *, boost::shared_ptr<const Glib::ustring>, R> { + public: + R operator()(const boost::function1<R, const unsigned char *> & func, const boost::shared_ptr<const Glib::ustring> & i) const + { + return func(reinterpret_cast<const unsigned char *>(i->c_str())); + } + }; + + template <typename T, typename R> + class LexicalVisitor : public boost::static_visitor<R> { + public: + typedef boost::function1<R, T> Func; + LexicalVisitor(Func f) : func(f) { + } + template <typename S> + R operator()(const S & i) const { + return lexical_run<T, S, R>()(func, i); + } + private: + Func func; + }; +} + +template <typename P, typename R> +R LexicalCall(const boost::function1<R, P> & f, const VariableType & s) +{ + return boost::apply_visitor<const LexicalVisitorHelper::LexicalVisitor<P, R>, const VariableType &>( + LexicalVisitorHelper::LexicalVisitor<P, R>(f), s); +} + +#endif + diff --git a/project2/iHaveParameters.cpp b/project2/iHaveParameters.cpp index bce857f..68d657a 100644 --- a/project2/iHaveParameters.cpp +++ b/project2/iHaveParameters.cpp @@ -25,7 +25,7 @@ IHaveParameters::Parameter::Parameter(const xmlpp::Element * p) : { } -const Glib::ustring & +VariableType IHaveParameters::getParameter(const Glib::ustring & name) const { Parameters::const_iterator i = parameters.find(name); diff --git a/project2/iHaveParameters.h b/project2/iHaveParameters.h index 8cfe8cd..9d5f46f 100644 --- a/project2/iHaveParameters.h +++ b/project2/iHaveParameters.h @@ -18,7 +18,7 @@ class IHaveParameters : public virtual IntrusivePtrBase { IHaveParameters(const xmlpp::Element * p); virtual ~IHaveParameters() = 0; - const Glib::ustring & getParameter(const Glib::ustring &) const; + VariableType getParameter(const Glib::ustring &) const; typedef boost::intrusive_ptr<Parameter> ParameterPtr; typedef std::map<Glib::ustring, ParameterPtr> Parameters; diff --git a/project2/presenter.cpp b/project2/presenter.cpp index 69300ec..c19846e 100644 --- a/project2/presenter.cpp +++ b/project2/presenter.cpp @@ -40,25 +40,25 @@ Presenter::pushSub(const Glib::ustring & name) const } void -Presenter::addAttr(const Glib::ustring & name, const Glib::ustring & value) const +Presenter::addAttr(const Glib::ustring & name, const VariableType & value) const { addAttr(name, Glib::ustring(), value); } void -Presenter::addAttr(const Glib::ustring & name, const Glib::ustring & ns, const Glib::ustring & value) const +Presenter::addAttr(const Glib::ustring & name, const Glib::ustring & ns, const VariableType & value) const { addField(name, ns, value); } void -Presenter::addField(const Glib::ustring & name, const Glib::ustring & value) const +Presenter::addField(const Glib::ustring & name, const VariableType & value) const { addField(name, Glib::ustring(), value); } void -Presenter::addField(const Glib::ustring & name, const Glib::ustring & ns, const Glib::ustring & value) const +Presenter::addField(const Glib::ustring & name, const Glib::ustring & ns, const VariableType & value) const { pushSub(name, ns); setText(value); diff --git a/project2/presenter.h b/project2/presenter.h index 13468f3..88807ae 100644 --- a/project2/presenter.h +++ b/project2/presenter.h @@ -16,11 +16,11 @@ class Presenter : public virtual CommonObjects, public virtual IntrusivePtrBase virtual void pushSub(const Glib::ustring & name) const; virtual void pushSub(const Glib::ustring & name, const Glib::ustring & ns) const = 0; - virtual void addAttr(const Glib::ustring & name, const Glib::ustring & value) const; - virtual void addAttr(const Glib::ustring & name, const Glib::ustring & ns, const Glib::ustring & value) const; - virtual void addField(const Glib::ustring & name, const Glib::ustring & value) const; - virtual void addField(const Glib::ustring & name, const Glib::ustring & ns, const Glib::ustring & value) const; - virtual void setText(const Glib::ustring & value) const = 0; + virtual void addAttr(const Glib::ustring & name, const VariableType & value) const; + virtual void addAttr(const Glib::ustring & name, const Glib::ustring & ns, const VariableType & value) const; + virtual void addField(const Glib::ustring & name, const VariableType & value) const; + virtual void addField(const Glib::ustring & name, const Glib::ustring & ns, const VariableType & value) const; + virtual void setText(const VariableType & value) const = 0; virtual void popSub() const = 0; void execute() const; diff --git a/project2/procRows.cpp b/project2/procRows.cpp index 25730d3..53a71b0 100644 --- a/project2/procRows.cpp +++ b/project2/procRows.cpp @@ -1,5 +1,6 @@ #include "procRows.h" #include "xmlObjectLoader.h" +#include "genericVisitor.h" #include <stdexcept> ElementLoaderImpl<ProcRows> procrowsLoader("procrows"); @@ -25,7 +26,7 @@ ProcRows::loadComplete(const CommonObjects *) FileStarChannel ProcRows::doOpen() const { - FILE * f = popen(path->c_str(), "re"); + FILE * f = LexicalCall<const char *, FILE *>(boost::bind(&popen, _1, "re"), path()); if (!f) { throw SubProcessFailedToStart(); } diff --git a/project2/regexCheck.cpp b/project2/regexCheck.cpp index 1af5fa1..edd2c38 100644 --- a/project2/regexCheck.cpp +++ b/project2/regexCheck.cpp @@ -1,6 +1,7 @@ #include "regexCheck.h" #include "xmlObjectLoader.h" #include "commonObjects.h" +#include "genericVisitor.h" #include <boost/regex.hpp> ElementLoaderImpl<RegexCheck> regexCheckLoader("regexcheck"); @@ -25,7 +26,12 @@ RegexCheck::loadComplete(const CommonObjects *) bool RegexCheck::performCheck() const { - const Glib::ustring & param(applyTo); - return boost::regex_match(param.begin(), param.end(), regex); + return LexicalCall<Glib::ustring, bool>(boost::bind(&RegexCheck::checkString, this, _1), applyTo()); +} + +bool +RegexCheck::checkString(const Glib::ustring & str) const +{ + return boost::regex_match(str.begin(), str.end(), regex); } diff --git a/project2/regexCheck.h b/project2/regexCheck.h index 818b11e..e2d5bc1 100644 --- a/project2/regexCheck.h +++ b/project2/regexCheck.h @@ -14,6 +14,8 @@ class RegexCheck : public ParamChecker { const Variable applyTo; const boost::regex regex; + private: + bool checkString(const Glib::ustring & str) const; }; #endif diff --git a/project2/rowSet.h b/project2/rowSet.h index d85f77b..b0bb668 100644 --- a/project2/rowSet.h +++ b/project2/rowSet.h @@ -29,8 +29,8 @@ class RowSet : public virtual SourceObject { virtual void setFilter(const Glib::ustring &) = 0; virtual unsigned int columnCount() const = 0; virtual const Glib::ustring & getColumnName(unsigned int col) const = 0; - virtual const Glib::ustring & getCurrentValue(const Glib::ustring & id) const = 0; - virtual const Glib::ustring & getCurrentValue(unsigned int col) const = 0; + virtual VariableType getCurrentValue(const Glib::ustring & id) const = 0; + virtual VariableType getCurrentValue(unsigned int col) const = 0; virtual bool isNull(unsigned int col) const = 0; virtual bool isNull(const Glib::ustring & id) const = 0; VariableType getRowNum() const; @@ -45,7 +45,7 @@ class RowSet : public virtual SourceObject { void rowChanged() const; protected: - mutable unsigned int rowNum; + mutable unsigned long int rowNum; private: static RowValuesStack stack; diff --git a/project2/sendmailTask.cpp b/project2/sendmailTask.cpp index 29d2c3b..60de51c 100644 --- a/project2/sendmailTask.cpp +++ b/project2/sendmailTask.cpp @@ -2,6 +2,7 @@ #include <boost/foreach.hpp> #include "xmlObjectLoader.h" #include "xmlPresenter.h" +#include "genericVisitor.h" #include <libxslt/transform.h> #include <misc.h> #include <stdexcept> @@ -65,16 +66,19 @@ class BoundaryEnd : public SendMailTask::MailPart { }; class Header : public SendMailTask::MailPart { public: - Header(const std::string & h, const Glib::ustring & v) : + Header(const std::string & h, const VariableType & v) : header(h), value(v) { } const char * write(char ** buf, int * len) { - *len = asprintf(buf, "%s: %s\r\n", header.c_str(), value.c_str()); + LexicalCall<const char *, void>(boost::bind(&Header::writeText, this, buf, len, _1), value); return (const char *)*buf; } private: + void writeText(char ** buf, int * len, const char * text) const { + *len = asprintf(buf, "%s: %s\r\n", header.c_str(), text); + } const std::string header; - const Glib::ustring value; + const VariableType & value; }; class HtmlContent : public SendMailTask::MailPart { public: @@ -164,9 +168,9 @@ SendMailTask::execute() const // Write email smtp_session_t session = smtp_create_session(); smtp_message_t message = smtp_add_message(session); - smtp_set_server(session, server().c_str()); + LexicalCall<const char *, void>(boost::bind(&smtp_set_server, session, _1), server()); smtp_set_header(message, "To", NULL, NULL); - smtp_add_recipient(message, to().c_str()); + LexicalCall<const char *, void>(boost::bind(&smtp_add_recipient, message, _1), to()); smtp_set_messagecb(message, writeMailWrapper, (SendMailTask*)this); if (!smtp_start_session(session)) { char buf[BUFSIZ]; diff --git a/project2/session.h b/project2/session.h index 8266acb..93b0303 100644 --- a/project2/session.h +++ b/project2/session.h @@ -5,18 +5,19 @@ #include <glibmm/ustring.h> #include <boost/intrusive_ptr.hpp> #include "intrusivePtrBase.h" +#include "variables.h" class Session : public virtual IntrusivePtrBase { public: class VariableNotFound : public std::exception { }; - typedef std::map<Glib::ustring, Glib::ustring> Values; + typedef std::map<Glib::ustring, VariableType> Values; Session(); virtual ~Session() = 0; - virtual Glib::ustring GetValue(const Glib::ustring & name) const = 0; + virtual const VariableType & GetValue(const Glib::ustring & name) const = 0; virtual Values GetValuesCopy() const = 0; - virtual void SetValue(const Glib::ustring & name, const Glib::ustring & value) = 0; + virtual void SetValue(const Glib::ustring & name, const VariableType & value) = 0; virtual void ClearValue(const Glib::ustring & name) = 0; virtual time_t ExpiryTime() const = 0; diff --git a/project2/sessionXml.cpp b/project2/sessionXml.cpp index 9e78aec..f7ff7c4 100644 --- a/project2/sessionXml.cpp +++ b/project2/sessionXml.cpp @@ -1,5 +1,6 @@ #include "sessionXml.h" #include "uuid.h" +#include "genericVisitor.h" #include <libxml++/nodes/element.h> #include <libxml++/parsers/domparser.h> #include <libxml++/nodes/textnode.h> @@ -14,9 +15,9 @@ class SessionXml : public Session { SessionXml(const xmlpp::Element *); virtual ~SessionXml(); - Glib::ustring GetValue(const Glib::ustring & name) const; + const VariableType & GetValue(const Glib::ustring & name) const; Values GetValuesCopy() const; - void SetValue(const Glib::ustring & name, const Glib::ustring & value); + void SetValue(const Glib::ustring & name, const VariableType & value); void ClearValue(const Glib::ustring & name); time_t ExpiryTime() const; void ExpiryTime(time_t); @@ -70,7 +71,7 @@ SessionContainerXml::CleanUp() sess->set_attribute("expires", boost::lexical_cast<Glib::ustring>(currentSession->expires)); BOOST_FOREACH(const SessionXml::Values::value_type & nvp, currentSession->vars) { xmlpp::Element * v = sess->add_child("var"); - v->add_child_text(nvp.second); + LexicalCall<Glib::ustring, void>(boost::bind(&xmlpp::Element::add_child_text, v, _1), nvp.second); v->set_attribute("name", nvp.first); } doc->write_to_file(xmlFile); @@ -118,7 +119,7 @@ SessionXml::SessionXml(const xmlpp::Element * p) : BOOST_FOREACH(const xmlpp::Node * n, xvars) { const xmlpp::Element * e = dynamic_cast<const xmlpp::Element *>(n); if (e) { - vars[e->get_attribute_value("name")] = e->get_child_text()->get_content(); + vars[e->get_attribute_value("name")] = e->get_child_text() ? e->get_child_text()->get_content() : ""; } } } @@ -139,7 +140,7 @@ SessionXml::ExpiryTime() const return expires; } -Glib::ustring +const VariableType & SessionXml::GetValue(const Glib::ustring & name) const { Values::const_iterator i = vars.find(name); @@ -150,7 +151,7 @@ SessionXml::GetValue(const Glib::ustring & name) const } void -SessionXml::SetValue(const Glib::ustring & name, const Glib::ustring & value) +SessionXml::SetValue(const Glib::ustring & name, const VariableType & value) { vars[name] = value; } diff --git a/project2/sqlCheck.cpp b/project2/sqlCheck.cpp index a65b379..3537134 100644 --- a/project2/sqlCheck.cpp +++ b/project2/sqlCheck.cpp @@ -5,6 +5,7 @@ #include "rdbmsDataSource.h" #include <boost/regex.hpp> #include "commonObjects.h" +#include "sqlVariableBinder.h" ElementLoaderImpl<SqlCheck> sqlCheckLoader("sqlcheck"); @@ -35,7 +36,7 @@ bool SqlCheck::performCheck() const { BOOST_FOREACH(Parameters::value_type p, parameters) { - query->bindParamS(atoi(p.second->name.c_str()), p.second->value); + boost::apply_visitor<const OdbcVariableBinder, const VariableType>(OdbcVariableBinder(query, atoi(p.second->name.c_str())), p.second->value); } bool retVal = false; while (query->fetch()) { diff --git a/project2/sqlMergeTask.cpp b/project2/sqlMergeTask.cpp index 156956a..b982473 100644 --- a/project2/sqlMergeTask.cpp +++ b/project2/sqlMergeTask.cpp @@ -2,6 +2,8 @@ #include "appEngine.h" #include "rdbmsDataSource.h" #include "exceptions.h" +#include "sqlVariableBinder.h" +#include "genericVisitor.h" #include <misc.h> #include <stdio.h> #include <stdexcept> @@ -24,7 +26,7 @@ class SqlMergeInsert : public IHaveParameters, public virtual SourceObject, publ void execute() const { unsigned int col = 0; BOOST_FOREACH(const Parameters::value_type & v, parameters) { - insert->bindParamS(col++, v.second->value); + boost::apply_visitor<const OdbcVariableBinder, const VariableType>(OdbcVariableBinder(insert, col++), v.second->value); } insert->execute(); } @@ -126,8 +128,7 @@ SqlMergeTask::execute() const BOOST_FOREACH(const Keys::value_type & k, keys) { tp.addKey(k); } - tp.patch(updateWhere->empty() ? NULL : updateWhere->c_str(), - patchOrder.empty() ? NULL : patchOrder.c_str()); + LexicalCall<const char *, void>(boost::bind(&TablePatch::patch, tp, _1, patchOrder.c_str()), updateWhere()); dropTempTable(); } @@ -242,7 +243,7 @@ class Populate : public NoOutputExecute { unsigned int cols = iter->columnCount(); for (unsigned int c = 0; c < cols; c += 1) { try { - cmd->bindParamS(idxs[c], iter->getCurrentValue(c)); + boost::apply_visitor<const OdbcVariableBinder, const VariableType>(OdbcVariableBinder(cmd, idxs[c]), iter->getCurrentValue(c)); } catch (const RowSet::FieldDoesNotExist &) { cmd->bindNull(idxs[c]); diff --git a/project2/sqlRows.cpp b/project2/sqlRows.cpp index 2e37b9c..0017352 100644 --- a/project2/sqlRows.cpp +++ b/project2/sqlRows.cpp @@ -8,6 +8,7 @@ #include <libxml++/nodes/textnode.h> #include "xmlObjectLoader.h" #include "commonObjects.h" +#include "sqlVariableBinder.h" ElementLoaderImpl<SqlRows> sqlviewLoader("sqlrows"); @@ -40,13 +41,13 @@ SqlRows::setFilter(const Glib::ustring & name) } } -const Glib::ustring & +VariableType SqlRows::getCurrentValue(const Glib::ustring & id) const { return (*query)[id].compose(); } -const Glib::ustring & +VariableType SqlRows::getCurrentValue(unsigned int col) const { return (*query)[col].compose(); @@ -189,7 +190,7 @@ SqlRows::SqlParameter::writeSql(Glib::ustring & sql) const void SqlRows::SqlParameter::bindParams(const RowProcessor * rp, ODBC::SelectCommand * cmd, unsigned int & offset) const { - cmd->bindParamS(offset++, rp->getParameter(name)); + boost::apply_visitor<const OdbcVariableBinder, const VariableType>(OdbcVariableBinder(cmd, offset++), rp->getParameter(name)); } SqlRows::SqlText::SqlText(const xmlpp::TextNode * n) : diff --git a/project2/sqlRows.h b/project2/sqlRows.h index 14ffb6f..9c6dadb 100644 --- a/project2/sqlRows.h +++ b/project2/sqlRows.h @@ -20,8 +20,8 @@ class SqlRows : public RowSet { virtual void setFilter(const Glib::ustring &); unsigned int columnCount() const; const Glib::ustring & getColumnName(unsigned int col) const; - const Glib::ustring & getCurrentValue(const Glib::ustring & id) const; - const Glib::ustring & getCurrentValue(unsigned int col) const; + VariableType getCurrentValue(const Glib::ustring & id) const; + VariableType getCurrentValue(unsigned int col) const; bool isNull(unsigned int col) const; bool isNull(const Glib::ustring & id) const; diff --git a/project2/sqlTask.cpp b/project2/sqlTask.cpp index 61bec1d..d5810be 100644 --- a/project2/sqlTask.cpp +++ b/project2/sqlTask.cpp @@ -4,6 +4,7 @@ #include "modifycommand.h" #include "rdbmsDataSource.h" #include "commonObjects.h" +#include "sqlVariableBinder.h" ElementLoaderImpl<SqlTask> sqltaskLoader("sqltask"); @@ -32,7 +33,7 @@ void SqlTask::execute() const { BOOST_FOREACH(Parameters::value_type p, parameters) { - modify->bindParamS(atoi(p.second->name.c_str()), p.second->value); + boost::apply_visitor<const OdbcVariableBinder, const VariableType>(OdbcVariableBinder(modify, atoi(p.second->name.c_str())), p.second->value); } modify->execute(); } diff --git a/project2/sqlVariableBinder.cpp b/project2/sqlVariableBinder.cpp new file mode 100644 index 0000000..f1e70da --- /dev/null +++ b/project2/sqlVariableBinder.cpp @@ -0,0 +1,70 @@ +#include "sqlVariableBinder.h" +#include "command.h" + +OdbcVariableBinder::OdbcVariableBinder(ODBC::Command * c, unsigned int i) : + cmd(c), + idx(i) +{ +} +void +OdbcVariableBinder::operator()(const Glib::ustring & i) const +{ + cmd->bindParamS(idx, i); +} +void +OdbcVariableBinder::operator()(const boost::shared_ptr<const Glib::ustring> & i) const +{ + cmd->bindParamS(idx, *i); +} +void +OdbcVariableBinder::operator()(const long long unsigned int & i) const +{ + cmd->bindParamI(idx, i); +} +void +OdbcVariableBinder::operator()(const long unsigned int & i) const +{ + cmd->bindParamI(idx, i); +} +void +OdbcVariableBinder::operator()(const unsigned int & i) const +{ + cmd->bindParamI(idx, i); +} +void +OdbcVariableBinder::operator()(const short unsigned int & i) const +{ + cmd->bindParamI(idx, i); +} +void +OdbcVariableBinder::operator()(const long long int & i) const +{ + cmd->bindParamI(idx, i); +} +void +OdbcVariableBinder::operator()(const long int & i) const +{ + cmd->bindParamI(idx, i); +} +void +OdbcVariableBinder::operator()(const int & i) const +{ + cmd->bindParamI(idx, i); +} +void +OdbcVariableBinder::operator()(const short int & i) const +{ + cmd->bindParamI(idx, i); +} +void +OdbcVariableBinder::operator()(const double & i) const +{ + cmd->bindParamF(idx, i); +} +void +OdbcVariableBinder::operator()(const float & i) const +{ + cmd->bindParamF(idx, i); +} + + diff --git a/project2/sqlVariableBinder.h b/project2/sqlVariableBinder.h new file mode 100644 index 0000000..ace2028 --- /dev/null +++ b/project2/sqlVariableBinder.h @@ -0,0 +1,33 @@ +#ifndef ODBCVARIABLEBINDER_H +#define ODBCVARIABLEBINDER_H + +#include <boost/variant.hpp> +#include <boost/shared_ptr.hpp> +#include <glibmm/ustring.h> + +namespace ODBC { + class Command; +} +class OdbcVariableBinder : public boost::static_visitor<> { + public: + OdbcVariableBinder(ODBC::Command * c, unsigned int i); + void operator()(const Glib::ustring & i) const; + void operator()(const boost::shared_ptr<const Glib::ustring> & i) const; + void operator()(const long long unsigned int & i) const; + void operator()(const long unsigned int & i) const; + void operator()(const unsigned int & i) const; + void operator()(const short unsigned int & i) const; + void operator()(const long long int & i) const; + void operator()(const long int & i) const; + void operator()(const int & i) const; + void operator()(const short int & i) const; + void operator()(const double & i) const; + void operator()(const float & i) const; + + private: + ODBC::Command * cmd; + unsigned int idx; +}; + +#endif + diff --git a/project2/tablepatch.cpp b/project2/tablepatch.cpp index 9ee5165..6f9c62f 100644 --- a/project2/tablepatch.cpp +++ b/project2/tablepatch.cpp @@ -37,8 +37,8 @@ TablePatch::patch(const char * where, const char * order) if (pk.size() == 0) { throw PatchCheckFailure(); } - doDeletes(where, order); - doUpdates(where, order); + doDeletes((where && *where) ? where : NULL, order); + doUpdates((where && *where) ? where : NULL, order); doInserts(order); } diff --git a/project2/urlRows.cpp b/project2/urlRows.cpp index cb0c24c..6032104 100644 --- a/project2/urlRows.cpp +++ b/project2/urlRows.cpp @@ -56,7 +56,7 @@ UrlRows::getColumnName(unsigned int col) const return columns[col]; } -const Glib::ustring & +VariableType UrlRows::getCurrentValue(unsigned int col) const { return *values[col]; @@ -74,7 +74,7 @@ UrlRows::isNull(const Glib::ustring & col) const return false; } -const Glib::ustring & +VariableType UrlRows::getCurrentValue(const Glib::ustring & id) const { Values::const_iterator v = values.begin(); diff --git a/project2/urlRows.h b/project2/urlRows.h index ea09fee..7b60400 100644 --- a/project2/urlRows.h +++ b/project2/urlRows.h @@ -17,8 +17,8 @@ class UrlRows : public RowSet { virtual void setFilter(const Glib::ustring &); unsigned int columnCount() const; const Glib::ustring & getColumnName(unsigned int col) const; - const Glib::ustring & getCurrentValue(const Glib::ustring & id) const; - const Glib::ustring & getCurrentValue(unsigned int col) const; + VariableType getCurrentValue(const Glib::ustring & id) const; + VariableType getCurrentValue(unsigned int col) const; bool isNull(unsigned int col) const; bool isNull(const Glib::ustring & id) const; diff --git a/project2/variables.cpp b/project2/variables.cpp index 5c4508f..c8b2571 100644 --- a/project2/variables.cpp +++ b/project2/variables.cpp @@ -3,37 +3,39 @@ #include "appEngine.h" #include "session.h" #include "rowUser.h" +#include "genericVisitor.h" #include <libxml++/nodes/textnode.h> #include <stdexcept> #include <syslog.h> #include <boost/tokenizer.hpp> #include <boost/foreach.hpp> #include <boost/algorithm/string/predicate.hpp> -#include <boost/lexical_cast.hpp> #include <boost/function.hpp> #include <boost/bind.hpp> class VariableLiteral : public VariableImpl { public: - VariableLiteral(const Glib::ustring & src) : VariableImpl(src) { } + VariableLiteral(const Glib::ustring & src) : VariableImpl(src), val(src) { } - virtual const Glib::ustring & value() const { return source; } + virtual const VariableType & value() const { return val; } + private: + VariableType val; }; class VariableImplDyn : public VariableImpl { public: VariableImplDyn(const Glib::ustring & src) : VariableImpl(src), cacheValid(false) { } - virtual const Glib::ustring & value() const = 0; + virtual const VariableType & value() const = 0; protected: - mutable Glib::ustring cache; + mutable VariableType cache; mutable bool cacheValid; }; class VariableSession : public VariableImplDyn { public: VariableSession(const Glib::ustring & src) : VariableImplDyn(src) { } - const Glib::ustring & value() const + const VariableType & value() const { try { cache = ApplicationEngine::getCurrent()->session()->GetValue(name); @@ -51,7 +53,7 @@ class VariableSession : public VariableImplDyn { class VariableParam : public VariableImplDyn { public: VariableParam(const Glib::ustring & src) : VariableImplDyn(src) { } - const Glib::ustring & value() const + const VariableType & value() const { if (!cacheValid) { try { @@ -72,7 +74,7 @@ class VariableParam : public VariableImplDyn { class VariableUri : public VariableImplDyn { public: VariableUri(const Glib::ustring & src) : VariableImplDyn(src) { } - const Glib::ustring & value() const + const VariableType & value() const { if (!cacheValid) { try { @@ -90,18 +92,7 @@ class VariableUri : public VariableImplDyn { } }; -template <class T> -static void assignHelper(Glib::ustring & dest, const T & src) { - const Glib::ustring * srcp = boost::get<const Glib::ustring>(&src); - if (srcp) { - dest = *srcp; - } - else { - dest = boost::lexical_cast<Glib::ustring>(src); - } -} -template <> -void assignHelper(Glib::ustring & dest, const Glib::ustring & src) { +static void assignHelper(VariableType & dest, const VariableType & src) { dest = src; } @@ -132,7 +123,7 @@ class VariableParent : public VariableImplDyn, public RowUser { } } } - const Glib::ustring & value() const + const VariableType & value() const { if (!cacheValid) { try { @@ -175,11 +166,11 @@ class VariableParent : public VariableImplDyn, public RowUser { void bind() const { if (attr) { - getValue = boost::bind(&assignHelper<VariableType>, _1, boost::bind(row->resolveAttr(name))); + getValue = boost::bind(&assignHelper, _1, boost::bind(row->resolveAttr(name))); } else { - typedef const Glib::ustring & (RowSet::*gCV)(const Glib::ustring &) const; - getValue = boost::bind(&assignHelper<Glib::ustring>, _1, + typedef VariableType (RowSet::*gCV)(const Glib::ustring &) const; + getValue = boost::bind(&assignHelper, _1, boost::bind((gCV)&RowSet::getCurrentValue, _2, name)); } } @@ -187,7 +178,7 @@ class VariableParent : public VariableImplDyn, public RowUser { const size_t depth; const bool attr; const RowUser * dep; - mutable boost::function2<void, Glib::ustring &, ConstRowSetPtr> getValue; + mutable boost::function2<void, VariableType &, ConstRowSetPtr> getValue; }; class VariableParse : public VariableImplDyn, public RowUser { @@ -200,21 +191,18 @@ class VariableParse : public VariableImplDyn, public RowUser { vars.push_back(Variable::create(t, this)); } } - const Glib::ustring & value() const + const VariableType & value() const { if (!cacheValid) { - size_t len = 0; - BOOST_FOREACH(Variable::VariableImplPtr vip, vars) { - len += vip->value().length() + 1; - } - cache.clear(); - cache.reserve(len); + Glib::ustring newCache; BOOST_FOREACH(Variable::VariableImplPtr v, vars) { - if (cache.length()) { - cache.append(" "); + if (newCache.length()) { + newCache.append(" "); } - cache.append(v->value()); + 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; diff --git a/project2/variables.h b/project2/variables.h index 8b3f7a4..469baa5 100644 --- a/project2/variables.h +++ b/project2/variables.h @@ -9,13 +9,30 @@ #include <libxml++/attribute.h> #include "intrusivePtrBase.h" #include <boost/variant.hpp> +#include <boost/shared_ptr.hpp> class RowUser; -typedef boost::variant<Glib::ustring, unsigned int, long int> VariableType; +typedef boost::variant< + // Strings + Glib::ustring, + boost::shared_ptr<const Glib::ustring>, + // Numbers + long long unsigned int, + long unsigned int, + unsigned int, + short unsigned int, + long long int, + long int, + int, + short int, + double, + float + // DateTimes (todo) + > VariableType; class VariableImpl : public virtual IntrusivePtrBase { public: - virtual const Glib::ustring & value() const = 0; + virtual const VariableType & value() const = 0; protected: VariableImpl(const Glib::ustring & src); @@ -23,7 +40,7 @@ class VariableImpl : public virtual IntrusivePtrBase { const Glib::ustring source; Glib::ustring name; - boost::optional<Glib::ustring> defaultValue; + boost::optional<VariableType> defaultValue; }; class Variable { @@ -36,9 +53,8 @@ class Variable { static Variable makeParent(const Glib::ustring & name, unsigned int depth); - operator const Glib::ustring & () const { return var->value(); } - const Glib::ustring & operator()() const { return var->value(); } - const Glib::ustring * operator->() const { return &var->value(); } + operator const VariableType & () const { return var->value(); } + const VariableType & operator()() const { return var->value(); } private: Variable(VariableImpl *); diff --git a/project2/xmlPresenter.cpp b/project2/xmlPresenter.cpp index af870eb..46b1ef1 100644 --- a/project2/xmlPresenter.cpp +++ b/project2/xmlPresenter.cpp @@ -1,4 +1,5 @@ #include "xmlPresenter.h" +#include "genericVisitor.h" XmlPresenter::~XmlPresenter() { @@ -36,15 +37,15 @@ XmlPresenter::pushSub(const Glib::ustring & name, const Glib::ustring & ns) cons } void -XmlPresenter::addAttr(const Glib::ustring & name, const Glib::ustring & ns, const Glib::ustring & value) const +XmlPresenter::addAttr(const Glib::ustring & name, const Glib::ustring & ns, const VariableType & value) const { - nodeStack.back()->set_attribute(name, value, ns); + LexicalCall<Glib::ustring, void>(boost::bind(&xmlpp::Element::set_attribute, nodeStack.back(), name, _1, ns), value); } void -XmlPresenter::setText(const Glib::ustring & value) const +XmlPresenter::setText(const VariableType & value) const { - nodeStack.back()->set_child_text(value); + LexicalCall<Glib::ustring, void>(boost::bind(&xmlpp::Element::set_child_text, nodeStack.back(), _1), value); } void diff --git a/project2/xmlPresenter.h b/project2/xmlPresenter.h index c16cc2c..ade2aaa 100644 --- a/project2/xmlPresenter.h +++ b/project2/xmlPresenter.h @@ -10,8 +10,8 @@ class XmlPresenter : public Presenter { ~XmlPresenter(); void pushSub(const Glib::ustring & name, const Glib::ustring & ns) const; - void addAttr(const Glib::ustring & name, const Glib::ustring & ns, const Glib::ustring & value) const; - void setText(const Glib::ustring & value) const; + void addAttr(const Glib::ustring & name, const Glib::ustring & ns, const VariableType & value) const; + void setText(const VariableType & value) const; void popSub() const; virtual XmlDocumentPtr getDataDocument() const; diff --git a/project2/xmlRows.cpp b/project2/xmlRows.cpp index 3582532..2f5bb4b 100644 --- a/project2/xmlRows.cpp +++ b/project2/xmlRows.cpp @@ -61,7 +61,7 @@ XmlRows::setFilter(const Glib::ustring &) throw NotSupported(__PRETTY_FUNCTION__); } -const Glib::ustring & +VariableType XmlRows::getCurrentValue(const Glib::ustring & id) const { Values::const_iterator i = values.find(id); @@ -71,7 +71,7 @@ XmlRows::getCurrentValue(const Glib::ustring & id) const return i->second; } -const Glib::ustring & +VariableType XmlRows::getCurrentValue(unsigned int col) const { Values::const_iterator i = values.find(fieldNames[col]); diff --git a/project2/xmlRows.h b/project2/xmlRows.h index b7fe790..df74710 100644 --- a/project2/xmlRows.h +++ b/project2/xmlRows.h @@ -20,8 +20,8 @@ class XmlRows : public RowSet { virtual void setFilter(const Glib::ustring &); unsigned int columnCount() const; const Glib::ustring & getColumnName(unsigned int col) const; - const Glib::ustring & getCurrentValue(const Glib::ustring & id) const; - const Glib::ustring & getCurrentValue(unsigned int col) const; + VariableType getCurrentValue(const Glib::ustring & id) const; + VariableType getCurrentValue(unsigned int col) const; bool isNull(unsigned int col) const; bool isNull(const Glib::ustring & id) const; diff --git a/project2/xslRows.cpp b/project2/xslRows.cpp index 696edb9..aa53540 100644 --- a/project2/xslRows.cpp +++ b/project2/xslRows.cpp @@ -3,6 +3,7 @@ #include "xml.h" #include "exceptions.h" #include "xmlObjectLoader.h" +#include "genericVisitor.h" #include <boost/lexical_cast.hpp> #include <libxml/HTMLparser.h> #include <libxml/xpath.h> @@ -101,7 +102,7 @@ XslRows::getDocument(const Glib::ustring & url) const void XslRows::execute(const RowProcessor * rp) const { - xmlDocPtr doc = getDocument(url()); + xmlDocPtr doc = LexicalCall<Glib::ustring, xmlDocPtr>(boost::bind(&XslRows::getDocument, this, _1), url()); xmlXPathContextPtr xpathCtx = xmlXPathNewContext(doc); if (!xpathCtx) { throw XpathInitError(); @@ -109,7 +110,7 @@ XslRows::execute(const RowProcessor * rp) const BOOST_FOREACH(const Namespaces::value_type & ns, namespaces) { xmlXPathRegisterNs(xpathCtx, BAD_CAST ns.first.c_str(), BAD_CAST ns.second.c_str()); } - xmlXPathObjectPtr xpathObj = xmlXPathEvalExpression(BAD_CAST fv->root().c_str(), xpathCtx); + xmlXPathObjectPtr xpathObj = LexicalCall<const xmlChar *, xmlXPathObjectPtr>(boost::bind(&xmlXPathEvalExpression, _1, xpathCtx), fv->root()); if (!xpathObj || !xpathObj->nodesetval) { xmlXPathFreeContext(xpathCtx); throw XpathEvalError(); @@ -120,14 +121,14 @@ XslRows::execute(const RowProcessor * rp) const xpathCtx->node = rowRoot; values.clear(); BOOST_FOREACH(const FilterView::XPaths::value_type & xp, fv->xpaths) { - xmlXPathObjectPtr xpathObjI = xmlXPathEvalExpression(BAD_CAST xp.second().c_str(), xpathCtx); + xmlXPathObjectPtr xpathObjI = LexicalCall<const xmlChar *, xmlXPathObjectPtr>(boost::bind(&xmlXPathEvalExpression, _1, xpathCtx), xp.second()); if (!xpathObjI) { xmlXPathFreeObject(xpathObj); xmlXPathFreeContext(xpathCtx); throw XpathEvalError(); } if (xpathObjI->floatval) { - values[xp.first] = boost::shared_ptr<const Glib::ustring>(new Glib::ustring(boost::lexical_cast<Glib::ustring>(xpathObjI->floatval))); + values[xp.first] = xpathObjI->floatval; } else if (xpathObjI->stringval) { values[xp.first] = boost::shared_ptr<const Glib::ustring>(new Glib::ustring((const char *)xpathObjI->stringval)); @@ -159,13 +160,13 @@ XslRows::FilterView::FilterView(const xmlpp::Element * p) : } } -const Glib::ustring & +VariableType XslRows::getCurrentValue(const Glib::ustring & id) const { - return *values.find(id)->second; + return values.find(id)->second; } -const Glib::ustring & +VariableType XslRows::getCurrentValue(unsigned int col) const { return getCurrentValue(getColumnName(col)); diff --git a/project2/xslRows.h b/project2/xslRows.h index 0cc92c7..e3aae63 100644 --- a/project2/xslRows.h +++ b/project2/xslRows.h @@ -18,8 +18,8 @@ class XslRows : public RowSet { virtual void setFilter(const Glib::ustring &); unsigned int columnCount() const; const Glib::ustring & getColumnName(unsigned int col) const; - const Glib::ustring & getCurrentValue(const Glib::ustring & id) const; - const Glib::ustring & getCurrentValue(unsigned int col) const; + VariableType getCurrentValue(const Glib::ustring & id) const; + VariableType getCurrentValue(unsigned int col) const; bool isNull(unsigned int col) const; bool isNull(const Glib::ustring & id) const; @@ -45,7 +45,7 @@ class XslRows : public RowSet { typedef std::map<const Glib::ustring, Glib::ustring> Namespaces; mutable Namespaces namespaces; - typedef std::map<const Glib::ustring, boost::shared_ptr<const Glib::ustring> > Values; + typedef std::map<const Glib::ustring, VariableType> Values; mutable Values values; typedef std::map<const Glib::ustring, boost::shared_ptr<xmlDoc> > Documents; mutable Documents documents; |