From 045aa16b69235429a651788891bcd56d2d50ac04 Mon Sep 17 00:00:00 2001 From: randomdan Date: Thu, 3 Feb 2011 12:45:52 +0000 Subject: Add missing conversion in generic visitor Whole new improved variable system (does drop VariableParse, no longer required) Add option to count, but not include, blank lines in proc and file rows File file rows to open files, not execute them Fix to ODBC API with strings that don't use the whole buffer XML changes to site to use new variable system Changes to GB importer to use FS rows and new SQL merge now that it's a) tested and b) variable parse has gone --- project2/fileRows.cpp | 22 +++-- project2/fileRows.h | 1 + project2/fsRows.cpp | 12 ++- project2/genericVisitor.h | 8 ++ project2/iHaveParameters.cpp | 2 +- project2/regexCheck.cpp | 2 +- project2/rowView.cpp | 3 +- project2/sendmailTask.cpp | 8 +- project2/sessionSetTask.cpp | 2 +- project2/sqlMergeTask.cpp | 2 +- project2/sqlRows.cpp | 4 +- project2/tablepatch.cpp | 186 +++++++++++++++++++------------------- project2/variables.cpp | 209 +++++++++++++++++++++++-------------------- project2/variables.h | 12 +-- 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 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(boost::bind(&popen, _1, "r"), path()); + FILE * f = LexicalCall(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 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(rp->getParameter("root")); + fsRoot = LexicalCall(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 &) { + catch (const boost::filesystem::basic_filesystem_error & 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 + class lexical_run, R> { + public: + R operator()(const boost::function1 & func, const boost::shared_ptr & i) const + { + return func(boost::lexical_cast(*i)); + } + }; template class lexical_run, 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 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(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 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 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 & c) { - variable = boost::shared_ptr(new Glib::ustring(&c[0], &c[c.size()])); + void string(const std::vector & c, size_t l) { + variable = boost::shared_ptr(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 #include +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(new Glib::ustring(src)); + if (type == "string") return src; + if (type == "int") return boost::lexical_cast(src); + if (type == "uint") return boost::lexical_cast(src); + if (type == "lint") return boost::lexical_cast(src); + if (type == "luint") return boost::lexical_cast(src); + if (type == "llint") return boost::lexical_cast(src); + if (type == "lluint") return boost::lexical_cast(src); + if (type == "float") return boost::lexical_cast(src); + if (type == "double") return boost::lexical_cast(src); + if (type == "datetime") return boost::posix_time::time_from_string(src); + if (type == "datetimeptr") return boost::shared_ptr(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 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 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 > tokens(source.raw(), boost::char_separator(" ")); - 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(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 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(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 defaultValue; }; class Variable { public: typedef boost::intrusive_ptr 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 xmlXPathObjectSPtr; + typedef boost::shared_ptr xmlXPathContextSPtr; xmlDocPtr doc = LexicalCall(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(boost::bind(&xmlXPathEvalExpression, _1, xpathCtx), fv->root()); + xmlXPathObjectSPtr xpathObj = xmlXPathObjectSPtr( + LexicalCall(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(boost::bind(&xmlXPathEvalExpression, _1, xpathCtx), xp.second()); + xmlXPathObjectSPtr xpathObjI = xmlXPathObjectSPtr(LexicalCall( + 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(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(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"))); } } } -- cgit v1.2.3