diff options
-rw-r--r-- | project2/fileRows.cpp | 22 | ||||
-rw-r--r-- | project2/fileRows.h | 1 | ||||
-rw-r--r-- | project2/fsRows.cpp | 12 | ||||
-rw-r--r-- | project2/genericVisitor.h | 8 | ||||
-rw-r--r-- | project2/iHaveParameters.cpp | 2 | ||||
-rw-r--r-- | project2/regexCheck.cpp | 2 | ||||
-rw-r--r-- | project2/rowView.cpp | 3 | ||||
-rw-r--r-- | project2/sendmailTask.cpp | 8 | ||||
-rw-r--r-- | project2/sessionSetTask.cpp | 2 | ||||
-rw-r--r-- | project2/sqlMergeTask.cpp | 2 | ||||
-rw-r--r-- | project2/sqlRows.cpp | 4 | ||||
-rw-r--r-- | project2/tablepatch.cpp | 186 | ||||
-rw-r--r-- | project2/variables.cpp | 209 | ||||
-rw-r--r-- | project2/variables.h | 12 | ||||
-rw-r--r-- | project2/xslRows.cpp | 24 |
15 files changed, 265 insertions, 232 deletions
diff --git a/project2/fileRows.cpp b/project2/fileRows.cpp index 28de335..036cf4c 100644 --- a/project2/fileRows.cpp +++ b/project2/fileRows.cpp @@ -10,10 +10,11 @@ ElementLoaderImpl<FileRows> filerowsLoader("filerows"); FileRows::FileRows(const xmlpp::Element * p) : SourceObject(p), RowSet(p), - path(p->get_attribute_value("path")), + path(p, "path"), fieldSep(p->get_attribute_value("fieldSep")[0]), quoteChar(p->get_attribute_value("quoteChar")[0]), keepBlankRows(p->get_attribute_value("keepBlankRows") == "true"), + countBlankRows(p->get_attribute_value("keepBlankRows") == "count"), newline(p->get_attribute_value("newline")), encoding(p->get_attribute_value("encoding")) { @@ -106,13 +107,18 @@ FileRows::execute(const RowProcessor * rp) const curCol++; } } - if (!mkCols && (keepBlankRows || !values.empty())) { - while (values.size() < columns.size()) { - values.push_back(ValPtr(new Glib::ustring())); - curCol++; + if (!mkCols) { + if (keepBlankRows || !values.empty()) { + while (values.size() < columns.size()) { + values.push_back(ValPtr(new Glib::ustring())); + curCol++; + } + rp->rowReady(); + rowNum += 1; + } + else if (countBlankRows) { + rowNum +=1; } - rp->rowReady(); - rowNum += 1; } values.clear(); } @@ -166,7 +172,7 @@ FileRows::addColumn(const Glib::ustring & rawtok) const FileStarChannel FileRows::doOpen() const { - FILE * f = LexicalCall<const char *, FILE *>(boost::bind(&popen, _1, "r"), path()); + FILE * f = LexicalCall<const char *, FILE *>(boost::bind(&fopen, _1, "r"), path()); if (!f) { throw FileNotReadable(); } diff --git a/project2/fileRows.h b/project2/fileRows.h index 0c5e3ce..1edff0b 100644 --- a/project2/fileRows.h +++ b/project2/fileRows.h @@ -40,6 +40,7 @@ class FileRows : public RowSet { gunichar fieldSep; gunichar quoteChar; bool keepBlankRows; + bool countBlankRows; std::string newline; std::string encoding; typedef std::vector<Glib::ustring> Columns; diff --git a/project2/fsRows.cpp b/project2/fsRows.cpp index 49bb57c..486dc90 100644 --- a/project2/fsRows.cpp +++ b/project2/fsRows.cpp @@ -135,14 +135,19 @@ FsRows::setFilter(const Glib::ustring &) { } +FsRows::Path +normalisePath(FsRows::Path & p) +{ + return (p / ".").remove_filename(); +} + void FsRows::execute(const RowProcessor * rp) const { rowNum = 1; depth = 0; - fsRoot = boost::lexical_cast<boost::filesystem::path>(rp->getParameter("root")); + fsRoot = LexicalCall<Path, Path>(boost::bind(&normalisePath, _1), rp->getParameter("root")); // Ensure there is a trailing / - fsRoot = (fsRoot / ".").remove_filename(); specs.clear(); SpecSpec s; typedef SpecSpec & (*splitter)(SpecSpec &, const Glib::ustring &, bool (*)(gunichar), boost::algorithm::token_compress_mode_type); @@ -187,7 +192,8 @@ FsRows::execute(const Path & dir, const RowProcessor * rp) const } } } - catch (const boost::filesystem::basic_filesystem_error<Path> &) { + catch (const boost::filesystem::basic_filesystem_error<Path> & e) { + fprintf(stderr, "err %s\n", e.what()); } depth -= 1; } diff --git a/project2/genericVisitor.h b/project2/genericVisitor.h index 2e66e19..ce45f3f 100644 --- a/project2/genericVisitor.h +++ b/project2/genericVisitor.h @@ -71,6 +71,14 @@ namespace LexicalVisitorHelper { return func(boost::posix_time::to_iso_extended_string(i)); } }; + template <typename T, typename S, typename R> + class lexical_run<T, boost::shared_ptr<const S>, R> { + public: + R operator()(const boost::function1<R, T> & func, const boost::shared_ptr<const S> & i) const + { + return func(boost::lexical_cast<T>(*i)); + } + }; template <typename S, typename R> class lexical_run<const char *, boost::shared_ptr<const S>, R> { public: diff --git a/project2/iHaveParameters.cpp b/project2/iHaveParameters.cpp index 68d657a..84adee5 100644 --- a/project2/iHaveParameters.cpp +++ b/project2/iHaveParameters.cpp @@ -21,7 +21,7 @@ IHaveParameters::~IHaveParameters() IHaveParameters::Parameter::Parameter(const xmlpp::Element * p) : name(p->get_attribute_value("name")), - value(p->get_attribute("value")) + value(p, "value") { } diff --git a/project2/regexCheck.cpp b/project2/regexCheck.cpp index edd2c38..5921a06 100644 --- a/project2/regexCheck.cpp +++ b/project2/regexCheck.cpp @@ -9,7 +9,7 @@ ElementLoaderImpl<RegexCheck> regexCheckLoader("regexcheck"); RegexCheck::RegexCheck(const xmlpp::Element * p) : SourceObject(p), ParamChecker(p), - applyTo(p->get_attribute("apply-to")), + applyTo(p, "apply-to"), regex(xmlChildText(p, "regex").raw()) { } diff --git a/project2/rowView.cpp b/project2/rowView.cpp index 10fece5..2306474 100644 --- a/project2/rowView.cpp +++ b/project2/rowView.cpp @@ -14,7 +14,8 @@ RowView::RowView(const xmlpp::Element * p) : BOOST_FOREACH(xmlpp::Node * node, p->find("columns/column")) { const xmlpp::Element * elem = dynamic_cast<const xmlpp::Element *>(node); if (elem) { - viewColumns.insert(Columns::value_type(elem->get_attribute_value("name"), Variable::makeParent(elem->get_child_text()->get_content(), 0))); + viewColumns.insert(Columns::value_type(elem->get_attribute_value("name"), + Variable::makeParent(elem->get_child_text()->get_content(), elem->get_attribute_value("source") == "attribute", 0))); } } LoaderBase loader("http://project2.randomdan.homeip.net", true); diff --git a/project2/sendmailTask.cpp b/project2/sendmailTask.cpp index 60de51c..7987d72 100644 --- a/project2/sendmailTask.cpp +++ b/project2/sendmailTask.cpp @@ -23,10 +23,10 @@ typedef boost::shared_ptr<xmlDoc> XmlDocumentPtr; SendMailTask::SendMailTask(const xmlpp::Element * p) : SourceObject(p), Task(p), - to(p->get_attribute("to")), - subject(p->get_attribute("subject")), - from(p->get_attribute("from")), - server(p->get_attribute("server")), + to(p, "to"), + subject(p, "subject"), + from(p, "from"), + server(p, "server"), present(p->get_attribute_value("present").raw()) { } diff --git a/project2/sessionSetTask.cpp b/project2/sessionSetTask.cpp index df96c66..a4b0e44 100644 --- a/project2/sessionSetTask.cpp +++ b/project2/sessionSetTask.cpp @@ -11,7 +11,7 @@ SessionSetTask::SessionSetTask(const xmlpp::Element * p) : SourceObject(p), Task(p), key(p->get_attribute_value("key")), - value(p->get_attribute("value")) + value(p, "value") { } diff --git a/project2/sqlMergeTask.cpp b/project2/sqlMergeTask.cpp index b982473..2436f1f 100644 --- a/project2/sqlMergeTask.cpp +++ b/project2/sqlMergeTask.cpp @@ -42,7 +42,7 @@ ElementLoaderImpl<SqlMergeInsert> sqlmergeinsertLoader("sqlmergeinsert"); SqlMergeTask::SqlMergeTask(const xmlpp::Element * p) : SourceObject(p), Task(p), - updateWhere(p->get_attribute_value("updatewhere")), + updateWhere(p, "updatewhere", false), patchOrder(p->get_attribute_value("patchorder")), earlyKeys(p->get_attribute_value("earlykeys") == "yes"), useView(p->get_attribute_value("useview") == "yes"), diff --git a/project2/sqlRows.cpp b/project2/sqlRows.cpp index d4c6cd8..31948df 100644 --- a/project2/sqlRows.cpp +++ b/project2/sqlRows.cpp @@ -45,8 +45,8 @@ SqlRows::setFilter(const Glib::ustring & name) class HandleAsVariableType : public ODBC::HandleField { public: void null() { } - void string(const std::vector<char> & c) { - variable = boost::shared_ptr<Glib::ustring>(new Glib::ustring(&c[0], &c[c.size()])); + void string(const std::vector<char> & c, size_t l) { + variable = boost::shared_ptr<Glib::ustring>(new Glib::ustring(&c[0], &c[l])); } void integer(SQLINTEGER i) { variable = i; diff --git a/project2/tablepatch.cpp b/project2/tablepatch.cpp index 6f9c62f..ddf7e03 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 && *where) ? where : NULL, order); - doUpdates((where && *where) ? where : NULL, order); + doDeletes(where, order); + doUpdates(where, order); doInserts(order); } @@ -91,7 +91,7 @@ TablePatch::doDeletes(const char * where, const char * order) if (where && *where) { toDelSql.appendf(" AND %s", where); } - if (order) { + if (order && *order) { toDelSql.appendf(" ORDER BY %s", order); } toDelSql.append(")"); @@ -102,100 +102,100 @@ TablePatch::doDeletes(const char * where, const char * order) void TablePatch::doUpdates(const char * where, const char * order) { - if (cols.size() == pk.size()) { - // Can't "change" anything... it's all part of the key - return; - } - // ----------------------------------------------------------------- - // Build SQL for list of updates to perform ------------------------ - // ----------------------------------------------------------------- - Buffer toUpdSel; - toUpdSel.append("SELECT "); - foreach (Columns::const_iterator, cols, col) { - if (pk.find(*col) == pk.end()) { - toUpdSel.appendf("b.%s, ", - col->c_str()); - } + if (cols.size() == pk.size()) { + // Can't "change" anything... it's all part of the key + return; } - foreach (Columns::const_iterator, cols, col) { - if (pk.find(*col) != pk.end()) { - toUpdSel.appendf("b.%s, ", - col->c_str()); - } - } - toUpdSel.appendf("0 FROM %s a, %s b", - dest.c_str(), src.c_str()); - foreach (PKI, pk, pki) { - if (pki == pk.begin()) { - toUpdSel.append(" WHERE "); - } - else { - toUpdSel.append(" AND "); - } - toUpdSel.appendf(" a.%s = b.%s", - pki->c_str(), pki->c_str()); - } - if (where && *where) { - toUpdSel.appendf(" AND %s", where); - } - toUpdSel.append(" AND ("); - bool first = true; - foreach (Columns::const_iterator, cols, col) { - if (pk.find(*col) == pk.end()) { - if (!first) { - toUpdSel.append(" OR "); - } - first = false; - toUpdSel.appendf( - " (((CASE WHEN (a.%s IS NULL AND b.%s IS NULL) THEN 1 ELSE 0 END) \ - + (CASE WHEN(a.%s = b.%s) THEN 1 ELSE 0 END)) = 0)", - col->c_str(), col->c_str(), col->c_str(), col->c_str()); - } - } - toUpdSel.append(")"); - if (order) { - toUpdSel.appendf(" ORDER BY %s", order); - } - // ----------------------------------------------------------------- - // Build SQL to perform updates ------------------------------------ - // ----------------------------------------------------------------- - Buffer updSql; - updSql.appendf("UPDATE %s SET ", - dest.c_str()); - first = true; - foreach (Columns::const_iterator, cols, col) { - if (pk.find(*col) == pk.end()) { - if (!first) { - updSql.append(", "); - } - first = false; - updSql.appendf(" %s = ?", - col->c_str()); - } - } - foreach (PKI, pk, pki) { - if (pki == pk.begin()) { - updSql.append(" WHERE "); - } - else { - updSql.append(" AND "); - } - updSql.appendf(" %s = ?", - pki->c_str()); - } - // ----------------------------------------------------------------- - // Iterator over update list make changes -------------------------- - // ----------------------------------------------------------------- - SelectCommand toUpd(db, toUpdSel); - ModifyCommand upd(db, updSql); - int cs = cols.size(); + // ----------------------------------------------------------------- + // Build SQL for list of updates to perform ------------------------ + // ----------------------------------------------------------------- + Buffer toUpdSel; + toUpdSel.append("SELECT "); + foreach (Columns::const_iterator, cols, col) { + if (pk.find(*col) == pk.end()) { + toUpdSel.appendf("b.%s, ", + col->c_str()); + } + } + foreach (Columns::const_iterator, cols, col) { + if (pk.find(*col) != pk.end()) { + toUpdSel.appendf("b.%s, ", + col->c_str()); + } + } + toUpdSel.appendf("0 FROM %s a, %s b", + dest.c_str(), src.c_str()); + foreach (PKI, pk, pki) { + if (pki == pk.begin()) { + toUpdSel.append(" WHERE "); + } + else { + toUpdSel.append(" AND "); + } + toUpdSel.appendf(" a.%s = b.%s", + pki->c_str(), pki->c_str()); + } + if (where && *where) { + toUpdSel.appendf(" AND %s", where); + } + toUpdSel.append(" AND ("); + bool first = true; + foreach (Columns::const_iterator, cols, col) { + if (pk.find(*col) == pk.end()) { + if (!first) { + toUpdSel.append(" OR "); + } + first = false; + toUpdSel.appendf( + " (((CASE WHEN (a.%s IS NULL AND b.%s IS NULL) THEN 1 ELSE 0 END) \ + + (CASE WHEN(a.%s = b.%s) THEN 1 ELSE 0 END)) = 0)", + col->c_str(), col->c_str(), col->c_str(), col->c_str()); + } + } + toUpdSel.append(")"); + if (order && *order) { + toUpdSel.appendf(" ORDER BY %s", order); + } + // ----------------------------------------------------------------- + // Build SQL to perform updates ------------------------------------ + // ----------------------------------------------------------------- + Buffer updSql; + updSql.appendf("UPDATE %s SET ", + dest.c_str()); + first = true; + foreach (Columns::const_iterator, cols, col) { + if (pk.find(*col) == pk.end()) { + if (!first) { + updSql.append(", "); + } + first = false; + updSql.appendf(" %s = ?", + col->c_str()); + } + } + foreach (PKI, pk, pki) { + if (pki == pk.begin()) { + updSql.append(" WHERE "); + } + else { + updSql.append(" AND "); + } + updSql.appendf(" %s = ?", + pki->c_str()); + } + // ----------------------------------------------------------------- + // Iterator over update list make changes -------------------------- + // ----------------------------------------------------------------- + SelectCommand toUpd(db, toUpdSel); + ModifyCommand upd(db, updSql); + int cs = cols.size(); toUpd.execute(); for (int c = 0; c < cs; c += 1) { toUpd[c].rebind(&upd, c); } - while (toUpd.fetch()) { - upd.execute(false); - } + while (toUpd.fetch()) { + upd.execute(false); + } } void @@ -247,7 +247,7 @@ TablePatch::doInserts(const char * order) toInsSql.appendf(" a.%s IS NULL", pki->c_str()); } - if (order) { + if (order && *order) { toInsSql.appendf(" ORDER BY %s", order); } ModifyCommand(db, toInsSql).execute(); 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)); } diff --git a/project2/variables.h b/project2/variables.h index 0b27419..2cccd5e 100644 --- a/project2/variables.h +++ b/project2/variables.h @@ -38,23 +38,17 @@ class VariableImpl : public virtual IntrusivePtrBase { virtual const VariableType & value() const = 0; protected: - VariableImpl(const Glib::ustring & src); virtual ~VariableImpl() = 0; - - const Glib::ustring source; - Glib::ustring name; - boost::optional<VariableType> defaultValue; }; class Variable { public: typedef boost::intrusive_ptr<VariableImpl> VariableImplPtr; - Variable(const xmlpp::Attribute *); - Variable(const xmlpp::Element *); - Variable(const Glib::ustring & s); + Variable(const xmlpp::Element *, const Glib::ustring & n, bool required = true, VariableType def = VariableType()); - static Variable makeParent(const Glib::ustring & name, unsigned int depth); + static Variable makeFromCode(const Glib::ustring & s); + static Variable makeParent(const Glib::ustring & name, bool attr, unsigned int depth); operator const VariableType & () const { return var->value(); } const VariableType & operator()() const { return var->value(); } diff --git a/project2/xslRows.cpp b/project2/xslRows.cpp index aa53540..0b981aa 100644 --- a/project2/xslRows.cpp +++ b/project2/xslRows.cpp @@ -20,7 +20,7 @@ class ResourceDownloadError : public std::exception { }; XslRows::XslRows(const xmlpp::Element * p) : SourceObject(p), RowSet(p), - url(p->get_attribute_value("url")), + url(p, "url"), html(p->get_attribute_value("html") == "true"), warnings(p->get_attribute_value("warnings") != "false") { @@ -102,17 +102,19 @@ XslRows::getDocument(const Glib::ustring & url) const void XslRows::execute(const RowProcessor * rp) const { + typedef boost::shared_ptr<xmlXPathObject> xmlXPathObjectSPtr; + typedef boost::shared_ptr<xmlXPathContext> xmlXPathContextSPtr; xmlDocPtr doc = LexicalCall<Glib::ustring, xmlDocPtr>(boost::bind(&XslRows::getDocument, this, _1), url()); - xmlXPathContextPtr xpathCtx = xmlXPathNewContext(doc); + xmlXPathContextSPtr xpathCtx = xmlXPathContextSPtr(xmlXPathNewContext(doc), xmlXPathFreeContext); if (!xpathCtx) { throw XpathInitError(); } BOOST_FOREACH(const Namespaces::value_type & ns, namespaces) { - xmlXPathRegisterNs(xpathCtx, BAD_CAST ns.first.c_str(), BAD_CAST ns.second.c_str()); + xmlXPathRegisterNs(xpathCtx.get(), BAD_CAST ns.first.c_str(), BAD_CAST ns.second.c_str()); } - xmlXPathObjectPtr xpathObj = LexicalCall<const xmlChar *, xmlXPathObjectPtr>(boost::bind(&xmlXPathEvalExpression, _1, xpathCtx), fv->root()); + xmlXPathObjectSPtr xpathObj = xmlXPathObjectSPtr( + LexicalCall<const xmlChar *, xmlXPathObjectPtr>(boost::bind(&xmlXPathEvalExpression, _1, xpathCtx.get()), fv->root()), xmlXPathFreeObject); if (!xpathObj || !xpathObj->nodesetval) { - xmlXPathFreeContext(xpathCtx); throw XpathEvalError(); } rowNum = 1; @@ -121,10 +123,9 @@ XslRows::execute(const RowProcessor * rp) const xpathCtx->node = rowRoot; values.clear(); BOOST_FOREACH(const FilterView::XPaths::value_type & xp, fv->xpaths) { - xmlXPathObjectPtr xpathObjI = LexicalCall<const xmlChar *, xmlXPathObjectPtr>(boost::bind(&xmlXPathEvalExpression, _1, xpathCtx), xp.second()); + xmlXPathObjectSPtr xpathObjI = xmlXPathObjectSPtr(LexicalCall<const xmlChar *, xmlXPathObjectPtr>( + boost::bind(&xmlXPathEvalExpression, _1, xpathCtx.get()), xp.second()), xmlXPathFreeObject); if (!xpathObjI) { - xmlXPathFreeObject(xpathObj); - xmlXPathFreeContext(xpathCtx); throw XpathEvalError(); } if (xpathObjI->floatval) { @@ -139,23 +140,20 @@ XslRows::execute(const RowProcessor * rp) const values[xp.first] = boost::shared_ptr<const Glib::ustring>(new Glib::ustring((const char *)val)); } } - xmlXPathFreeObject(xpathObjI); } rp->rowReady(); rowNum += 1; } - xmlXPathFreeObject(xpathObj); - xmlXPathFreeContext(xpathCtx); } XslRows::FilterView::FilterView(const xmlpp::Element * p) : name(p->get_attribute_value("name")), - root(p->get_attribute_value("root")) + root(p, "root") { BOOST_FOREACH(const xmlpp::Node * node, p->find("field")) { const xmlpp::Element * elem = dynamic_cast<const xmlpp::Element *>(node); if (elem) { - xpaths.insert(XPaths::value_type(elem->get_attribute_value("name"), elem->get_attribute_value("xpath"))); + xpaths.insert(XPaths::value_type(elem->get_attribute_value("name"), Variable(elem, "xpath"))); } } } |