From d1132f0e4b4952fc9718d748e33aa43a6f0fb67f Mon Sep 17 00:00:00 2001 From: randomdan Date: Tue, 9 Aug 2011 19:46:16 +0000 Subject: Strip out some dead wood Fix a few small things But many fix the big idiot problem with storing state in the rowset instance --- project2/Jamfile.jam | 2 +- project2/columns.cpp | 23 ++++++ project2/columns.h | 33 +++++++++ project2/console/consoleAppEngine.h | 4 +- project2/definedColumns.cpp | 75 +++----------------- project2/definedColumns.h | 53 +++++--------- project2/fileRows.cpp | 8 +-- project2/fileRows.h | 2 +- project2/fileStrmVarWriter.cpp | 2 + project2/fsRows.cpp | 137 +++++++++++++++--------------------- project2/fsRows.h | 60 ++++++++-------- project2/iterate.cpp | 30 +------- project2/iterate.h | 2 +- project2/regexRows.cpp | 22 ++---- project2/regexRows.h | 5 +- project2/rowProcessor.h | 4 +- project2/rowSet.cpp | 71 +++++++++++++++---- project2/rowSet.h | 44 +++++++----- project2/rowView.cpp | 25 ++----- project2/rowView.h | 2 +- project2/safeMapFind.h | 27 +++++++ project2/scopeObject.cpp | 23 ++++++ project2/scopeObject.h | 20 ++++++ project2/sqlMergeTask.cpp | 65 +++++++---------- project2/sqlMergeTask.h | 4 +- project2/sqlRows.cpp | 78 ++++++++------------ project2/sqlRows.h | 18 ++--- project2/streamRows.cpp | 136 ++++++++++++++--------------------- project2/streamRows.h | 33 +++++---- project2/tablepatch.cpp | 2 + project2/tablepatch.h | 6 +- project2/urlRows.cpp | 20 ++---- project2/urlRows.h | 6 +- project2/variables-modlookup.cpp | 12 ++-- project2/variables.cpp | 12 ++-- project2/xmlRows.cpp | 88 ++++++----------------- project2/xmlRows.h | 21 +++--- project2/xslRows.cpp | 81 +++++++-------------- project2/xslRows.h | 32 +++++---- 39 files changed, 586 insertions(+), 702 deletions(-) create mode 100644 project2/columns.cpp create mode 100644 project2/columns.h create mode 100644 project2/safeMapFind.h create mode 100644 project2/scopeObject.cpp create mode 100644 project2/scopeObject.h diff --git a/project2/Jamfile.jam b/project2/Jamfile.jam index 5eb1c27..80befb9 100644 --- a/project2/Jamfile.jam +++ b/project2/Jamfile.jam @@ -58,7 +58,7 @@ lib p2common : iterate.cpp paramChecker.cpp presenter.cpp rawView.cpp logger.cpp if.cpp xmlScriptParser.cpp viewHost.cpp sourceObject.cpp task.cpp variables.cpp variableConvert.cpp view.cpp xmlObjectLoader.cpp exceptions.cpp sessionClearTask.cpp session.cpp sessionSetTask.cpp commonObjects.cpp xmlPresenter.cpp taskHost.cpp checkHost.cpp - rowView.cpp rowSet.cpp rowProcessor.cpp config.cpp fileStrmVarWriter.cpp noOutputExecute.cpp + rowView.cpp rowSet.cpp rowProcessor.cpp config.cpp fileStrmVarWriter.cpp noOutputExecute.cpp columns.cpp scopeObject.cpp transform.cpp transformHtml.cpp transformText.cpp definedColumns.cpp structExceptHandling.cpp validDateCheck.cpp variables-modconfig.cpp variables-modlookup.cpp diff --git a/project2/columns.cpp b/project2/columns.cpp new file mode 100644 index 0000000..a2511f6 --- /dev/null +++ b/project2/columns.cpp @@ -0,0 +1,23 @@ +#include "columns.h" +#include + +Column::Column(unsigned int i, const xmlpp::Element * p) : + idx(i), + name(p->get_attribute("name") ? p->get_attribute_value("name") : p->get_child_text()->get_content()), + defValue(p, "default", false) +{ +} + +Column::Column(unsigned int i, const Glib::ustring & n, const Variable & v) : + idx(i), + name(n), + defValue(v) +{ +} + +Column * +Column::make(unsigned int idx, const xmlpp::Element * p) +{ + return new Column(idx, p); +} + diff --git a/project2/columns.h b/project2/columns.h new file mode 100644 index 0000000..8b9b9b3 --- /dev/null +++ b/project2/columns.h @@ -0,0 +1,33 @@ +#ifndef COLUMNS_H +#define COLUMNS_H + +#include +#include "variables.h" +#include +#include +#include + +class Column : public IntrusivePtrBase { + public: + Column(unsigned int idx, const xmlpp::Element * p); + Column(unsigned int i, const Glib::ustring & n, const Variable & v = Variable(Null())); + + static Column * make(unsigned int idx, const xmlpp::Element * p); + + const unsigned int idx; + const Glib::ustring name; + const Variable defValue; +}; + +struct byColIdx {}; +struct byColName {}; +typedef boost::multi_index::multi_index_container, + boost::multi_index::indexed_by< + boost::multi_index::ordered_unique< + boost::multi_index::tag, BOOST_MULTI_INDEX_MEMBER(Column, const Glib::ustring, name)>, + boost::multi_index::ordered_unique< + boost::multi_index::tag, BOOST_MULTI_INDEX_MEMBER(Column, const unsigned int, idx)> + > > Columns; + +#endif + diff --git a/project2/console/consoleAppEngine.h b/project2/console/consoleAppEngine.h index 3d54a18..5e0a403 100644 --- a/project2/console/consoleAppEngine.h +++ b/project2/console/consoleAppEngine.h @@ -1,5 +1,5 @@ -#ifndef CGIAPPENGINE_H -#define CGIAPPENGINE_H +#ifndef CONSOLEAPPENGINE_H +#define CONSOLEAPPENGINE_H #include "../appEngine.h" #include "../task.h" diff --git a/project2/definedColumns.cpp b/project2/definedColumns.cpp index 1361453..5260e51 100644 --- a/project2/definedColumns.cpp +++ b/project2/definedColumns.cpp @@ -1,84 +1,31 @@ #include "definedColumns.h" -#include +#include #include -DefinedColumns::DefinedColumns(const xmlpp::Element * p) : - RowSet(p) +DefinedColumns::DefinedColumns(const xmlpp::Element * p, const Glib::ustring & colPath, const ColCreator & func) { unsigned int colNo = 0; - BOOST_FOREACH(const xmlpp::Node * node, p->find("columns/column")) { + BOOST_FOREACH(const xmlpp::Node * node, p->find(colPath)) { const xmlpp::Element * elem = dynamic_cast(node); if (elem) { - columns.insert(Column(colNo++, elem)); + columns.insert(func(colNo++, elem)); } } } -DefinedColumns::Column::Column(unsigned int i, const Glib::ustring & c) : - idx(i), - col(c), - defValue(VariableType()) +ColumnValues::ColumnValues(const DefinedColumns * rs) : + rowSet(rs) { + fields.resize(rs->columns.size()); } -DefinedColumns::Column::Column(unsigned int i, const xmlpp::Element * p) : - idx(i), - col(p->get_child_text()->get_content()), - defValue(p, "default", false) +ColumnValues::~ColumnValues() { } -void -DefinedColumns::Column::operator=(const VariableType & v) const +const Columns & +ColumnValues::getColumns() const { - value = v; -} - -const Glib::ustring & -DefinedColumns::getColumnName(unsigned int col) const -{ - Columns::index::type::iterator i = columns.get().find(col); - if (i != columns.get().end()) { - return i->col; - } - throw RowSet::FieldOutOfRange(col); -} - -unsigned int -DefinedColumns::columnCount() const -{ - return columns.size(); -} - -VariableType -DefinedColumns::getCurrentValue(unsigned int col) const -{ - Columns::index::type::iterator i = columns.get().find(col); - if (i != columns.get().end()) { - return i->value; - } - throw RowSet::FieldOutOfRange(col); -} - -bool -DefinedColumns::isNull(unsigned int col) const -{ - return (columns.get().find(col) == columns.get().end()); -} - -bool -DefinedColumns::isNull(const Glib::ustring & col) const -{ - return (columns.get().find(col) == columns.get().end()); -} - -VariableType -DefinedColumns::getCurrentValue(const Glib::ustring & col) const -{ - Columns::const_iterator i = columns.get().find(col); - if (i != columns.end()) { - return i->value; - } - throw RowSet::FieldDoesNotExist(col); + return rowSet->columns; } diff --git a/project2/definedColumns.h b/project2/definedColumns.h index d6f2ba3..2fc6bbd 100644 --- a/project2/definedColumns.h +++ b/project2/definedColumns.h @@ -2,47 +2,26 @@ #define DEFINEDCOLUMNS_H #include -#include -#include -#include +#include #include "variables.h" #include "rowSet.h" +#include "columns.h" -class DefinedColumns : public RowSet { +class DefinedColumns { public: - DefinedColumns(const xmlpp::Element *); - - unsigned int columnCount() const; - const Glib::ustring & getColumnName(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; - - protected: - class Column { - public: - Column(unsigned int idx, const Glib::ustring &); - Column(unsigned int idx, const xmlpp::Element * p); - - void operator=(const VariableType &) const; - - const unsigned int idx; - const Glib::ustring col; - mutable VariableType value; - const Variable defValue; - }; - struct byColIdx {}; - struct byColName {}; - typedef boost::multi_index::multi_index_container< - Column, - boost::multi_index::indexed_by< - boost::multi_index::ordered_unique< - boost::multi_index::tag, BOOST_MULTI_INDEX_MEMBER(Column, const Glib::ustring, col)>, - boost::multi_index::ordered_unique< - boost::multi_index::tag, BOOST_MULTI_INDEX_MEMBER(Column, const unsigned int, idx)> - > > Columns; - mutable Columns columns; + typedef boost::function2 ColCreator; + DefinedColumns(const xmlpp::Element * p, const Glib::ustring & colPath, const ColCreator & func); + Columns columns; +}; + +class ColumnValues : public RowState { + public: + ColumnValues(const DefinedColumns *); + virtual ~ColumnValues(); + + virtual const Columns & getColumns() const; + + const DefinedColumns * const rowSet; }; #endif diff --git a/project2/fileRows.cpp b/project2/fileRows.cpp index 58dde13..d7c8fca 100644 --- a/project2/fileRows.cpp +++ b/project2/fileRows.cpp @@ -29,17 +29,15 @@ FileRows::setFilter(const Glib::ustring &) } void -FileRows::execute(const RowProcessor * rp) const +FileRows::execute(const Glib::ustring &, const RowProcessor * rp) const { - rowNum = 1; FileStarChannel c(doOpen()); c.set_encoding(encoding); gunichar ch; - begin(); + ParseState ps(this, rp); while (c.read(ch) == Glib::IO_STATUS_NORMAL) { - this->pushChar(ch, rp); + this->pushChar(ch, ps); } - end(rp); } FileStarChannel diff --git a/project2/fileRows.h b/project2/fileRows.h index a4cc863..0cf3f1d 100644 --- a/project2/fileRows.h +++ b/project2/fileRows.h @@ -12,7 +12,7 @@ class FileRows : public StreamRows { FileRows(const xmlpp::Element * p); ~FileRows(); - void execute(const RowProcessor *) const; + void execute(const Glib::ustring &, const RowProcessor *) const; virtual void loadComplete(const CommonObjects *); virtual void setFilter(const Glib::ustring &); diff --git a/project2/fileStrmVarWriter.cpp b/project2/fileStrmVarWriter.cpp index 1af99dc..51fb487 100644 --- a/project2/fileStrmVarWriter.cpp +++ b/project2/fileStrmVarWriter.cpp @@ -49,9 +49,11 @@ void FileStreamVariableWriter::operator()(const double & i) const { fprintf(out, "%g", i); } void FileStreamVariableWriter::operator()(const Glib::ustring & i) const { + fputc('\'', out); if (fwrite(i.c_str(), i.bytes(), 1, out) < 1) { // Care much? None of the others check. } + fputc('\'', out); } void FileStreamVariableWriter::operator()(const boost::posix_time::ptime & i) const { fprintf(out, "[%s]", boost::posix_time::to_iso_extended_string(i).c_str()); diff --git a/project2/fsRows.cpp b/project2/fsRows.cpp index 5ae8221..b308f38 100644 --- a/project2/fsRows.cpp +++ b/project2/fsRows.cpp @@ -28,17 +28,24 @@ const Glib::ustring field_group("owningGroup"); const Glib::ustring field_mode("mode"); const Glib::ustring field_perms("perms"); const Glib::ustring field_type("type"); +static +Columns defCols() { + Columns rtn; + rtn.insert(new Column(0, "absPath")); + return rtn; +} +const Columns FsRows::SearchState::col(defCols()); -bool FsRows::SpecBase::recurse(const FsRows *) const { return true; } -bool FsRows::SpecBase::matches(const FsRows *) const { return true; } -const boost::filesystem::path & FsRows::SpecBase::curPath(const FsRows * fs) const { return fs->curPath; } -unsigned int FsRows::SpecBase::depth(const FsRows * fs) const { return fs->depth; } -struct stat & FsRows::SpecBase::curStat(const FsRows * fs) const { return fs->curStat; } +bool FsRows::SpecBase::recurse(const SearchState *) const { return true; } +bool FsRows::SpecBase::matches(const SearchState *) const { return true; } +const boost::filesystem::path & FsRows::SpecBase::curPath(const SearchState * fs) const { return fs->curPath; } +unsigned int FsRows::SpecBase::depth(const SearchState * fs) const { return fs->depth; } +const struct stat & FsRows::SpecBase::curStat(const SearchState * fs) const { return fs->curStat; } class FsRowSpecName : public FsRows::SpecBase { public: FsRowSpecName(const Glib::ustring & v) : pattern(v) { } - bool matches(const FsRows * fs) const { + bool matches(const FsRows::SearchState * fs) const { // Based on code written by Jack Handy - jakkhandy@hotmail.com // from http://www.codeproject.com/KB/string/wildcmp.aspx Glib::ustring::const_iterator wild = pattern.begin(); @@ -85,7 +92,7 @@ class FsRowSpecName : public FsRows::SpecBase { class FsRowSpecType : public FsRows::SpecBase { public: FsRowSpecType(const Glib::ustring & v) : types(v) { } - bool matches(const FsRows * fs) const { + bool matches(const FsRows::SearchState * fs) const { if (S_ISREG(curStat(fs).st_mode)) { return types.find('f') != Glib::ustring::npos; } @@ -114,7 +121,7 @@ class FsRowSpecType : public FsRows::SpecBase { class FsRowSpecMaxDepth : public FsRows::SpecBase { public: FsRowSpecMaxDepth(const Glib::ustring & v) : maxDepth(boost::lexical_cast(v)) { } - bool recurse(const FsRows * fs) const { + bool recurse(const FsRows::SearchState * fs) const { return (depth(fs) < maxDepth); } const unsigned int maxDepth; @@ -134,11 +141,6 @@ FsRows::loadComplete(const CommonObjects *) { } -void -FsRows::setFilter(const Glib::ustring &) -{ -} - FsRows::Path normalisePath(const std::string & p) { @@ -150,12 +152,9 @@ normalisePath(const std::string & p) } void -FsRows::execute(const RowProcessor * rp) const +FsRows::execute(const Glib::ustring &, const RowProcessor * rp) const { - rowNum = 1; - depth = 0; - fsRoot = normalisePath(rp->getParameter("root")); - specs.clear(); + SearchState ss(normalisePath(rp->getParameter("root"))); SpecSpec s; typedef SpecSpec & (*splitter)(SpecSpec &, const Glib::ustring &, bool (*)(gunichar), boost::algorithm::token_compress_mode_type); splitter split = &boost::algorithm::split; @@ -163,134 +162,108 @@ FsRows::execute(const RowProcessor * rp) const for (SpecSpec::const_iterator sf = s.begin(); sf != s.end(); ) { const Glib::ustring & name = (*sf++); if (name == "-name") { - specs.insert(new FsRowSpecName(*sf++)); + ss.specs.insert(new FsRowSpecName(*sf++)); } else if (name == "-type") { - specs.insert(new FsRowSpecType(*sf++)); + ss.specs.insert(new FsRowSpecType(*sf++)); } else if (name == "-maxdepth") { - specs.insert(new FsRowSpecMaxDepth(*sf++)); + ss.specs.insert(new FsRowSpecMaxDepth(*sf++)); } else { throw NotSupported(name); } } - execute(fsRoot, rp); + execute(ss, ss.fsRoot, rp); } void -FsRows::execute(const Path & dir, const RowProcessor * rp) const +FsRows::execute(SearchState & ss, const Path & dir, const RowProcessor * rp) const { - depth += 1; + ss.depth += 1; try { DirEnt end; for (DirEnt itr(dir); itr != end; ++itr) { - curPathStr = itr->path().string(); - curPath = itr->path(); - stat(curPathStr.c_str(), &curStat); + ss.curPathStr = itr->path().string(); + ss.curPath = itr->path(); + stat(ss.curPathStr.c_str(), &ss.curStat); - if (boost::algorithm::all(specs, boost::bind(&SpecBase::matches, _1, this))) { - rp->rowReady(); - rowNum += 1; + if (boost::algorithm::all(ss.specs, boost::bind(&SpecBase::matches, _1, &ss))) { + ss.process(rp); } - if (S_ISDIR(curStat.st_mode) && boost::algorithm::all(specs, boost::bind(&SpecBase::recurse, _1, this))) { - execute(*itr, rp); + if (S_ISDIR(ss.curStat.st_mode) && boost::algorithm::all(ss.specs, boost::bind(&SpecBase::recurse, _1, &ss))) { + execute(ss, *itr, rp); } } } catch (const boost::filesystem::filesystem_error & e) { Logger()->messagef(LOG_WARNING, "%s when processing '%s'", e.what(), dir.string().c_str()); } - depth -= 1; + ss.depth -= 1; } -unsigned int -FsRows::columnCount() const -{ - return 1; -} - -bool -FsRows::isNull(unsigned int) const -{ - return false; -} - -bool -FsRows::isNull(const Glib::ustring &) const -{ - return false; -} - -VariableType -FsRows::getCurrentValue(const Glib::ustring &) const -{ - return curPathStr; -} - -VariableType -FsRows::getCurrentValue(unsigned int) const +FsRows::SearchState::SearchState(const Path & dir) : + fsRoot(dir) { - return curPathStr; } -const Glib::ustring & -FsRows::getColumnName(unsigned int) const +const Columns & +FsRows::SearchState::getColumns() const { - return field_absPath; + return col; } -RowSet::RowAttribute -FsRows::resolveAttr(const Glib::ustring & a) const +RowState::RowAttribute +FsRows::SearchState::resolveAttr(const Glib::ustring & a) const { if (a == field_relPath) { - return boost::bind(&FsRows::fileRelPath, this); + return boost::bind(&FsRows::SearchState::fileRelPath, this); } if (a == field_size) { - return boost::bind(&FsRows::fileSize, this); + return boost::bind(&FsRows::SearchState::fileSize, this); } if (a == field_modDate) { - return boost::bind(&FsRows::fileModDate, this); + return boost::bind(&FsRows::SearchState::fileModDate, this); } if (a == field_user) { - return boost::bind(&FsRows::fileUser, this); + return boost::bind(&FsRows::SearchState::fileUser, this); } if (a == field_group) { - return boost::bind(&FsRows::fileGroup, this); + return boost::bind(&FsRows::SearchState::fileGroup, this); } if (a == field_mode) { - return boost::bind(&FsRows::fileMode, this); + return boost::bind(&FsRows::SearchState::fileMode, this); } if (a == field_perms) { - return boost::bind(&FsRows::filePerms, this); + return boost::bind(&FsRows::SearchState::filePerms, this); } if (a == field_type) { - return boost::bind(&FsRows::fileType, this); + return boost::bind(&FsRows::SearchState::fileType, this); } - return RowSet::resolveAttr(a); + return RowState::resolveAttr(a); } VariableType -FsRows::fileRelPath() const +FsRows::SearchState::fileRelPath() const { return curPathStr.substr(fsRoot.string().length() - 1); } VariableType -FsRows::fileSize() const +FsRows::SearchState::fileSize() const { return curStat.st_size; } VariableType -FsRows::fileModDate() const +FsRows::SearchState::fileModDate() const { return boost::posix_time::from_time_t(curStat.st_mtime); } VariableType -FsRows::fileUser() const +FsRows::SearchState::fileUser() const { struct passwd * p = getpwuid(curStat.st_uid); if (p) { @@ -302,7 +275,7 @@ FsRows::fileUser() const } VariableType -FsRows::fileGroup() const +FsRows::SearchState::fileGroup() const { struct group * g = getgrgid(curStat.st_gid); if (g) { @@ -314,19 +287,19 @@ FsRows::fileGroup() const } VariableType -FsRows::fileMode() const +FsRows::SearchState::fileMode() const { throw NotSupported(__PRETTY_FUNCTION__); } VariableType -FsRows::filePerms() const +FsRows::SearchState::filePerms() const { throw NotSupported(__PRETTY_FUNCTION__); } VariableType -FsRows::fileType() const +FsRows::SearchState::fileType() const { throw NotSupported(__PRETTY_FUNCTION__); } diff --git a/project2/fsRows.h b/project2/fsRows.h index 4e559cd..8cd1a9f 100644 --- a/project2/fsRows.h +++ b/project2/fsRows.h @@ -13,14 +13,15 @@ class CommonObjects; /// Project2 component to create a row set based on files and directories on the local filesystem class FsRows : public RowSet { public: + class SearchState; class SpecBase : public virtual IntrusivePtrBase { public: - virtual bool recurse(const FsRows * fs) const; - virtual bool matches(const FsRows * fs) const; + virtual bool recurse(const SearchState * fs) const; + virtual bool matches(const SearchState * fs) const; protected: - const boost::filesystem::path & curPath(const FsRows * fs) const; - unsigned int depth(const FsRows * fs) const; - struct stat & curStat(const FsRows * fs) const; + const boost::filesystem::path & curPath(const SearchState * fs) const; + unsigned int depth(const SearchState * fs) const; + const struct stat & curStat(const SearchState * fs) const; }; typedef boost::intrusive_ptr SpecBasePtr; typedef std::set SpecBases; @@ -30,35 +31,34 @@ class FsRows : public RowSet { FsRows(const xmlpp::Element * p); ~FsRows(); - void execute(const RowProcessor *) const; + void execute(const Glib::ustring &, const RowProcessor *) const; virtual void loadComplete(const CommonObjects *); - virtual void setFilter(const Glib::ustring &); - unsigned int columnCount() const; - const Glib::ustring & getColumnName(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; + class SearchState : public RowState { + public: + SearchState(const boost::filesystem::path & r); - VariableType fileRelPath() const; - VariableType fileSize() const; - VariableType fileModDate() const; - VariableType fileUser() const; - VariableType fileGroup() const; - VariableType fileMode() const; - VariableType filePerms() const; - VariableType fileType() const; + virtual RowAttribute resolveAttr(const Glib::ustring & attrName) const; + virtual const Columns & getColumns() const; - protected: - void execute(const Path & dir, const RowProcessor *) const; - mutable SpecBases specs; - mutable boost::filesystem::path fsRoot; - mutable boost::filesystem::path curPath; - mutable Glib::ustring curPathStr; - mutable unsigned int depth; - mutable struct stat curStat; + VariableType fileRelPath() const; + VariableType fileSize() const; + VariableType fileModDate() const; + VariableType fileUser() const; + VariableType fileGroup() const; + VariableType fileMode() const; + VariableType filePerms() const; + VariableType fileType() const; + static const Columns col; + SpecBases specs; + const boost::filesystem::path fsRoot; + boost::filesystem::path curPath; + Glib::ustring curPathStr; + unsigned int depth; + struct stat curStat; + }; + protected: + void execute(SearchState &, const Path & dir, const RowProcessor *) const; friend class SpecBase; }; diff --git a/project2/iterate.cpp b/project2/iterate.cpp index 795b356..99c5004 100644 --- a/project2/iterate.cpp +++ b/project2/iterate.cpp @@ -26,7 +26,7 @@ Iterate::loadComplete(const CommonObjects * co) } void -Iterate::rowReady() const +Iterate::rowReady(const RowState *) const { executeChildren(); } @@ -34,38 +34,14 @@ Iterate::rowReady() const void Iterate::execute() const { - if (!filter.empty()) { - source->setFilter(filter); - } - RowSet::beginRow(source.get()); - try { - source->execute(this); - RowSet::endRow(source.get()); - } - catch (...) { - RowSet::endRow(source.get()); - throw; - } + source->execute(filter, this); } void Iterate::executeChildren() const { BOOST_FOREACH(const Tasks::value_type & sq, normal) { - if (dynamic_cast(sq.get())) { - sq->execute(); - } - else { - RowSet::beginRow(NULL); - try { - sq->execute(); - RowSet::endRow(NULL); - } - catch (...) { - RowSet::endRow(NULL); - throw; - } - } + sq->execute(); } } diff --git a/project2/iterate.h b/project2/iterate.h index 9ea0f94..50fd879 100644 --- a/project2/iterate.h +++ b/project2/iterate.h @@ -16,7 +16,7 @@ class Iterate : public IHaveSubTasks, public RowProcessor { virtual ~Iterate(); void loadComplete(const CommonObjects *); - void rowReady() const; + void rowReady(const RowState *) const; void execute() const; protected: diff --git a/project2/regexRows.cpp b/project2/regexRows.cpp index 6d75d3a..1dab636 100644 --- a/project2/regexRows.cpp +++ b/project2/regexRows.cpp @@ -7,7 +7,8 @@ DECLARE_LOADER("regexrows", RegexRows); RegexRows::RegexRows(const xmlpp::Element * p) : - DefinedColumns(p), + DefinedColumns(p, "columns/column", boost::bind(&Column::make, _1, _2)), + RowSet(p), sourceText(p, "sourceText"), regex(p, "regex") { @@ -23,28 +24,19 @@ RegexRows::loadComplete(const CommonObjects*) } void -RegexRows::setFilter(const Glib::ustring&) +RegexRows::execute(const Glib::ustring&, const RowProcessor * rp) const { -} - -void -RegexRows::execute(const RowProcessor * rp) const -{ - rowNum = 1; Glib::RefPtr reg = Glib::Regex::create(regex(), Glib::REGEX_CASELESS | Glib::REGEX_DOTALL); Glib::MatchInfo matches; if (reg->match(sourceText(), matches)) { + ColumnValues cv(this); do { - unsigned int cols = std::min(matches.get_match_count(), DefinedColumns::columnCount() + 1); + unsigned int cols = std::min(matches.get_match_count(), cv.rowSet->columns.size() + 1); unsigned int n; for (n = 1; n < cols; n += 1) { - *DefinedColumns::columns.get().find(n - 1) = matches.fetch(n); - } - for (; n < DefinedColumns::columnCount() + 1; n += 1) { - *DefinedColumns::columns.get().find(n - 1) = Null(); + cv.fields[n - 1] = matches.fetch(n); } - rp->rowReady(); - rowNum += 1; + cv.process(rp); } while (matches.next()); } } diff --git a/project2/regexRows.h b/project2/regexRows.h index b4b6446..cef2e71 100644 --- a/project2/regexRows.h +++ b/project2/regexRows.h @@ -5,13 +5,12 @@ #include "variables.h" /// Base class for Project2 components that create a row set based on the contents of a byte stream -class RegexRows : public DefinedColumns { +class RegexRows : public DefinedColumns, public RowSet { public: RegexRows(const xmlpp::Element * p); ~RegexRows(); void loadComplete(const CommonObjects*); - void setFilter(const Glib::ustring&); - void execute(const RowProcessor*) const; + void execute(const Glib::ustring&, const RowProcessor*) const; private: const Variable sourceText; diff --git a/project2/rowProcessor.h b/project2/rowProcessor.h index 0f421f9..38142e5 100644 --- a/project2/rowProcessor.h +++ b/project2/rowProcessor.h @@ -10,7 +10,6 @@ class RowProcessor : public IHaveParameters { public: RowProcessor(const xmlpp::Element *); - virtual void rowReady() const = 0; void loadComplete(const CommonObjects *); const std::string recordSource; @@ -18,6 +17,9 @@ class RowProcessor : public IHaveParameters { protected: boost::intrusive_ptr source; + private: + friend class RowState; + virtual void rowReady(const RowState *) const = 0; }; #endif diff --git a/project2/rowSet.cpp b/project2/rowSet.cpp index cfbb9cf..acc9246 100644 --- a/project2/rowSet.cpp +++ b/project2/rowSet.cpp @@ -1,15 +1,16 @@ #include "rowSet.h" #include "commonObjects.h" +#include "scopeObject.h" #include "logger.h" #include "variables.h" +#include "rowProcessor.h" #include #include -RowSet::RowValuesStack RowSet::stack; +RowState::RowValuesStack RowState::stack; RowSet::RowSet(const xmlpp::Element * p) : - SourceObject(p), - rowNum(-1) + SourceObject(p) { } @@ -17,34 +18,76 @@ RowSet::~RowSet() { } +RowState::RowState() : + rowNum(0) +{ +} + +RowState::~RowState() +{ +} + void -RowSet::beginRow(const RowSet * r) +RowState::process(const RowProcessor * rp, bool r) { - stack.push_back(r); + rowNum += 1; + stack.push_back(this); + ScopeObject s(boost::bind(&RowState::RowValuesStack::pop_back, &stack)); + rp->rowReady(this); + if (r) { + reset(); + } } void -RowSet::endRow(const RowSet * r) +RowState::reset() { - if (stack.back() != r) { - Logger()->messagef(LOG_CRIT, "%s: stack is corrupted", __PRETTY_FUNCTION__); - std::abort(); + BOOST_FOREACH(FieldValues::value_type & v, fields) { + v = Null(); } - stack.pop_back(); +} + +void +RowState::blankRow() +{ + rowNum += 1; } VariableType -RowSet::getRowNum() const +RowState::getRowNum() const { return rowNum; } -RowSet::RowAttribute -RowSet::resolveAttr(const Glib::ustring & attrName) const +RowState::RowAttribute +RowState::resolveAttr(const Glib::ustring & attrName) const { if (attrName == "rownum") { - return boost::bind(&RowSet::getRowNum, this); + return boost::bind(&RowState::getRowNum, this); } throw AttributeDoesNotExist(attrName); } +VariableType +RowState::getCurrentValue(const Glib::ustring & col) const +{ + const Columns & columns = getColumns(); + Columns::index::type::iterator di = columns.get().find(col); + if (di != columns.get().end()) { + if (!boost::get(&fields[(*di)->idx])) { + return fields[(*di)->idx]; + } + return (*di)->defValue; + } + throw RowSet::FieldDoesNotExist(col); +} + +void +RowState::foreachColumn(const ColumnAction & action) const +{ + const Columns & columns = getColumns(); + BOOST_FOREACH(const Columns::value_type & col, columns.get()) { + action(col->idx, col->name, (!boost::get(&fields[col->idx])) ? fields[col->idx] : col->defValue()); + } +} + diff --git a/project2/rowSet.h b/project2/rowSet.h index a907cd2..a9919f9 100644 --- a/project2/rowSet.h +++ b/project2/rowSet.h @@ -5,6 +5,7 @@ #include #include "sourceObject.h" #include "exceptions.h" +#include "columns.h" #include class RowProcessor; @@ -13,37 +14,48 @@ class VariableType; typedef boost::intrusive_ptr RowSetPtr; typedef boost::intrusive_ptr ConstRowSetPtr; +class RowState; + /// Base class for Project2 components that provide a row set representation of data class RowSet : public SourceObject { public: - typedef boost::function0 RowAttribute; SimpleNumericException(ParentOutOfRange); - SimpleMessageException(AttributeDoesNotExist); SimpleMessageException(FieldDoesNotExist); SimpleNumericException(FieldOutOfRange); - typedef std::vector RowValuesStack; + RowSet(const xmlpp::Element *); virtual ~RowSet() = 0; - virtual void setFilter(const Glib::ustring &) = 0; - virtual unsigned int columnCount() const = 0; - virtual const Glib::ustring & getColumnName(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; + virtual void execute(const Glib::ustring &, const RowProcessor *) const = 0; +}; + +class RowState { + public: + RowState(); + virtual ~RowState(); + + typedef boost::function0 RowAttribute; + typedef boost::function3 ColumnAction; + SimpleMessageException(AttributeDoesNotExist); + VariableType getRowNum() const; - virtual void execute(const RowProcessor *) const = 0; + void process(const RowProcessor *, bool reset = true); + void blankRow(); + void reset(); + virtual VariableType getCurrentValue(const Glib::ustring & id) const; virtual RowAttribute resolveAttr(const Glib::ustring & attrName) const; + void foreachColumn(const ColumnAction & action) const; + virtual const Columns & getColumns() const = 0; + + typedef std::vector FieldValues; + FieldValues fields; - static const RowValuesStack & Stack() { return stack; } - static void beginRow(const RowSet * r); - static void endRow(const RowSet * r); - protected: - mutable unsigned long int rowNum; + typedef std::vector RowValuesStack; + static const RowValuesStack & Stack() { return stack; } private: + unsigned int rowNum; static RowValuesStack stack; }; diff --git a/project2/rowView.cpp b/project2/rowView.cpp index 8e22c4b..2ac5081 100644 --- a/project2/rowView.cpp +++ b/project2/rowView.cpp @@ -1,7 +1,9 @@ #include "rowView.h" #include "presenter.h" +#include "scopeObject.h" #include "xmlObjectLoader.h" #include +#include #include DECLARE_LOADER("view", RowView); @@ -36,14 +38,11 @@ RowView::loadComplete(const CommonObjects * co) } void -RowView::rowReady() const +RowView::rowReady(const RowState * rs) const { presenter->pushSub(recordName); if (viewColumns.empty()) { - unsigned int cols = source->columnCount(); - for (unsigned int c = 0; c < cols; c += 1) { - presenter->addField(source->getColumnName(c), source->getCurrentValue(c)); - } + rs->foreachColumn(boost::bind(&Presenter::addField, presenter, _2, _3)); } else { BOOST_FOREACH(const Columns::value_type & col, viewColumns) { @@ -57,22 +56,10 @@ RowView::rowReady() const void RowView::execute(const Presenter * p) const { - if (!filter.empty()) { - source->setFilter(filter); - } presenter = p; presenter->pushSub(rootName); - RowSet::beginRow(source.get()); - try { - source->execute(this); - RowSet::endRow(source.get()); - presenter->popSub(); - } - catch (...) { - presenter->popSub(); - RowSet::endRow(source.get()); - throw; - } + ScopeObject pres(boost::bind(&Presenter::popSub, p)); + source->execute(filter, this); } void diff --git a/project2/rowView.h b/project2/rowView.h index 3652e37..c065414 100644 --- a/project2/rowView.h +++ b/project2/rowView.h @@ -14,7 +14,7 @@ class RowView : public View, public RowProcessor { void loadComplete(const CommonObjects *); void execute(const Presenter *) const; - void rowReady() const; + void rowReady(const RowState *) const; const Glib::ustring rootName; const Glib::ustring recordName; diff --git a/project2/safeMapFind.h b/project2/safeMapFind.h new file mode 100644 index 0000000..b27caf3 --- /dev/null +++ b/project2/safeMapFind.h @@ -0,0 +1,27 @@ +#ifndef SAFEMAPFIND_H +#define SAFEMAPFIND_H + +template +typename Map::const_iterator +safeMapFind(const Map & map, const typename Map::key_type & key) +{ + typename Map::const_iterator i = map.find(key); + if (i == map.end()) { + throw Ex(key); + } + return i; +} + +template +typename Map::mapped_type +defaultMapFind(const Map & map, const typename Map::key_type & key, const typename Map::mapped_type & def = typename Map::mapped_type()) +{ + typename Map::const_iterator i = map.find(key); + if (i == map.end()) { + return def; + } + return i->second; +} + +#endif + diff --git a/project2/scopeObject.cpp b/project2/scopeObject.cpp new file mode 100644 index 0000000..268fd2c --- /dev/null +++ b/project2/scopeObject.cpp @@ -0,0 +1,23 @@ +#include "scopeObject.h" +#include "logger.h" + +ScopeObject::ScopeObject(const Event & onexitpre, const Event & onsuccess, const Event & onfailure, const Event & onexitpost) : + onExitPre(onexitpre), + onSuccess(onsuccess), + onFailure(onfailure), + onExitPost(onexitpost) +{ +} + +ScopeObject::~ScopeObject() +{ + if (onExitPre) onExitPre(); + if (std::uncaught_exception()) { + if (onFailure) onFailure(); + } + else { + if (onSuccess) onSuccess(); + } + if (onExitPost) onExitPost(); +} + diff --git a/project2/scopeObject.h b/project2/scopeObject.h new file mode 100644 index 0000000..d019e7d --- /dev/null +++ b/project2/scopeObject.h @@ -0,0 +1,20 @@ +#ifndef SCOPE_OBJECT_H +#define SCOPE_OBJECT_H + +#include + +class ScopeObject { + public: + typedef boost::function0 Event; + ScopeObject(const Event &, const Event & = Event(), const Event & = Event(), const Event & = Event()); + ~ScopeObject(); + + private: + const Event onExitPre; + const Event onSuccess; + const Event onFailure; + const Event onExitPost; +}; + +#endif + diff --git a/project2/sqlMergeTask.cpp b/project2/sqlMergeTask.cpp index fdc6340..2c38bf1 100644 --- a/project2/sqlMergeTask.cpp +++ b/project2/sqlMergeTask.cpp @@ -1,4 +1,5 @@ #include "sqlMergeTask.h" +#include "columns.h" #include "commonObjects.h" #include "rdbmsDataSource.h" #include "exceptions.h" @@ -9,10 +10,11 @@ #include #include #include +#include #include bool SqlMergeTask::defaultUseTempTable = true; -static void attach(boost::intrusive_ptr i, ModifyCommand * insert); +static void attach(boost::intrusive_ptr i, DB::ModifyCommand * insert); class SqlMergeInsert; typedef boost::intrusive_ptr SqlMergeInsertPtr; @@ -34,8 +36,8 @@ class SqlMergeInsert : IHaveParameters, public Task { insert->execute(); } private: - friend void attach(SqlMergeInsertPtr i, ModifyCommand * insert); - ModifyCommand * insert; + friend void attach(SqlMergeInsertPtr i, DB::ModifyCommand * insert); + DB::ModifyCommand * insert; }; DECLARE_LOADER("sqlmerge", SqlMergeTask); @@ -139,7 +141,7 @@ void SqlMergeTask::createTempTable() const { if (useView) { - ModifyCommand * cv = destdb->newModifyCommand(stringf( + DB::ModifyCommand * cv = destdb->newModifyCommand(stringf( "CREATE VIEW %s AS %s", dtablet.c_str(), boost::algorithm::join(sqls, " UNION ").c_str())); @@ -147,7 +149,7 @@ SqlMergeTask::createTempTable() const delete cv; } else { - ModifyCommand * ctt = destdb->newModifyCommand(stringf( + DB::ModifyCommand * ctt = destdb->newModifyCommand(stringf( "CREATE TEMPORARY TABLE %s AS SELECT * FROM %s WHERE 0=1", dtablet.c_str(), dtable.c_str())); @@ -155,7 +157,7 @@ SqlMergeTask::createTempTable() const delete ctt; BOOST_FOREACH(Columns::value_type c, cols) { if (!c->maptable.empty()) { - ModifyCommand * at = destdb->newModifyCommand(stringf( + DB::ModifyCommand * at = destdb->newModifyCommand(stringf( "ALTER TABLE %s ADD COLUMN %s VARCHAR(1000)", dtablet.c_str(), c->mapcolumn.c_str())); @@ -170,7 +172,7 @@ void SqlMergeTask::dropTempTable() const { if (tempTableCreated) { - ModifyCommand * d; + DB::ModifyCommand * d; if (useView) { d = destdb->newModifyCommand("DROP VIEW " + dtablet); } @@ -190,13 +192,13 @@ SqlMergeTask::createTempKey() const idx.appendf("ALTER TABLE %s ADD CONSTRAINT pk_%s PRIMARY KEY(%s)", dtablet.c_str(), dtablet.c_str(), boost::algorithm::join(keys, ", ").c_str()); - ModifyCommand * at = destdb->newModifyCommand(idx); + DB::ModifyCommand * at = destdb->newModifyCommand(idx); at->execute(); delete at; /* Indexes */ int n = 0; BOOST_FOREACH(const Keys::value_type & i, indexes) { - ModifyCommand * ci = destdb->newModifyCommand(stringf( + DB::ModifyCommand * ci = destdb->newModifyCommand(stringf( "CREATE INDEX idx_%s_%d ON %s(%s)", dtablet.c_str(), n, dtablet.c_str(), i.c_str())); ci->execute(); @@ -204,7 +206,7 @@ SqlMergeTask::createTempKey() const n += 1; } } -ModifyCommand * +DB::ModifyCommand * SqlMergeTask::insertCommand() const { Buffer ins; @@ -230,7 +232,7 @@ SqlMergeTask::insertCommand() const class Populate : public NoOutputExecute { public: - Populate(ModifyCommand * c) : + Populate(DB::ModifyCommand * c) : SourceObject(__FUNCTION__), NoOutputExecute(__FUNCTION__), cmd(c) @@ -241,40 +243,21 @@ class Populate : public NoOutputExecute { } void execute() const { - const RowSet * iter = *++RowSet::Stack().rbegin(); - if (idxs.empty()) { - idxs.resize(iter->columnCount()); - // Sure this can be improved upon... but hey. - // Find each columns alphabetical index - unsigned int cols = iter->columnCount(); - for (unsigned int c = 0; c < cols; c += 1) { - idxs[c] = 0; - for (unsigned int d = 0; d < cols; d += 1) { - if (c != d && iter->getColumnName(d) < iter->getColumnName(c)) { - idxs[c]++; - } - } - } - } - unsigned int cols = iter->columnCount(); - for (unsigned int c = 0; c < cols; c += 1) { - try { - boost::apply_visitor(SqlVariableBinder(cmd, idxs[c]), iter->getCurrentValue(c)); - } - catch (const RowSet::FieldDoesNotExist &) { - cmd->bindNull(idxs[c]); - } - } + unsigned int idx = 0; + RowState::Stack().back()->foreachColumn(boost::bind(&Populate::bind, this, boost::ref(idx), _3)); cmd->execute(); } private: - mutable std::vector idxs; - ModifyCommand * cmd; + void bind(unsigned int & idx, const VariableType & value) const + { + boost::apply_visitor(SqlVariableBinder(cmd, idx++), value); + } + DB::ModifyCommand * cmd; }; typedef boost::intrusive_ptr PopulatePtr; void -attach(SqlMergeInsertPtr i, ModifyCommand * insert) +attach(SqlMergeInsertPtr i, DB::ModifyCommand * insert) { if (i) { i->insert = insert; @@ -282,7 +265,7 @@ attach(SqlMergeInsertPtr i, ModifyCommand * insert) } static void -attach(boost::intrusive_ptr i, ModifyCommand * insert) +attach(boost::intrusive_ptr i, DB::ModifyCommand * insert) { if (!i) { return; @@ -322,13 +305,13 @@ SqlMergeTask::copyToTempTable() const ins.append((*c)->column); } ins.appendf(" FROM (%s) tmp_src", sql.c_str()); - ModifyCommand * cttt = destdb->newModifyCommand(ins); + DB::ModifyCommand * cttt = destdb->newModifyCommand(ins); cttt->execute(); delete cttt; } BOOST_FOREACH(Columns::value_type c, cols) { if (!c->maptable.empty()) { - ModifyCommand * utt = destdb->newModifyCommand( + DB::ModifyCommand * utt = destdb->newModifyCommand( stringf( "UPDATE %s d SET %s = (SELECT m.%s FROM %s m WHERE m.%s = d.%s) WHERE %s IS NULL", dtablet.c_str(), diff --git a/project2/sqlMergeTask.h b/project2/sqlMergeTask.h index fc72a93..c9e206c 100644 --- a/project2/sqlMergeTask.h +++ b/project2/sqlMergeTask.h @@ -62,8 +62,8 @@ class SqlMergeTask : public Task { Sources sources; std::list sqls; protected: - ModifyCommand * insertCommand() const; - ModifyCommand * insCmd; + DB::ModifyCommand * insertCommand() const; + DB::ModifyCommand * insCmd; public: const DB::Connection * destdb; diff --git a/project2/sqlRows.cpp b/project2/sqlRows.cpp index 2b8745f..fb2de33 100644 --- a/project2/sqlRows.cpp +++ b/project2/sqlRows.cpp @@ -33,15 +33,6 @@ SqlRows::loadComplete(const CommonObjects * co) db = co->dataSource(dataSource()); } -void -SqlRows::setFilter(const Glib::ustring & name) -{ - SqlCommand::FiltersRangeType r = sqlCommand.filters.equal_range(name); - for (SqlCommand::Filters::const_iterator i = r.first; i != r.second; i++) { - i->second->active = true; - } -} - class HandleAsVariableType : public DB::HandleField { public: void null() { @@ -62,58 +53,45 @@ class HandleAsVariableType : public DB::HandleField { VariableType variable; }; -VariableType -SqlRows::getCurrentValue(const Glib::ustring & id) const -{ - HandleAsVariableType h; - (*query)[id].apply(h); - return h.variable; -} - -VariableType -SqlRows::getCurrentValue(unsigned int col) const -{ - HandleAsVariableType h; - (*query)[col].apply(h); - return h.variable; -} - -bool -SqlRows::isNull(unsigned int col) const +SqlRows::SqlState::SqlState(SelectPtr s) : + query(s) { - return (*query)[col].isNull(); } -bool -SqlRows::isNull(const Glib::ustring & col) const +const Columns & +SqlRows::SqlState::getColumns() const { - return (*query)[col].isNull(); -} - -unsigned int -SqlRows::columnCount() const -{ - return query->columnCount(); -} - -const Glib::ustring & -SqlRows::getColumnName(unsigned int col) const -{ - return (*query)[col].name; + if (columns.empty()) { + for (unsigned int c = 0; c < query->columnCount(); c++) { + columns.insert(new Column(c, (*query)[c].name)); + } + } + return columns; } void -SqlRows::execute(const RowProcessor * rp) const +SqlRows::execute(const Glib::ustring & filter, const RowProcessor * rp) const { - rowNum = 1; + SqlCommand::FiltersRangeType r = sqlCommand.filters.equal_range(filter); + for (SqlCommand::Filters::const_iterator i = r.first; i != r.second; i++) { + i->second->active = true; + } unsigned int offset = 0; Glib::ustring sql; sqlCommand.writeSql(sql); - query = SelectPtr(db->getReadonly().newSelectCommand(sql)); - sqlCommand.bindParams(rp, query.get(), offset); - while (query->fetch()) { - rp->rowReady(); - rowNum += 1; + SqlState ss(SelectPtr(db->getReadonly().newSelectCommand(sql))); + sqlCommand.bindParams(rp, ss.query.get(), offset); + while (ss.query->fetch()) { + HandleAsVariableType h; + if (ss.fields.empty()) { + ss.fields.resize(ss.query->columnCount()); + } + for (unsigned int c = 0; c < ss.query->columnCount(); c++) { + const DB::Column & col = (*ss.query)[c]; + col.apply(h); + ss.fields[c] = h.variable; + } + ss.process(rp); } } diff --git a/project2/sqlRows.h b/project2/sqlRows.h index 901023b..10f57f1 100644 --- a/project2/sqlRows.h +++ b/project2/sqlRows.h @@ -16,15 +16,8 @@ class SqlRows : public RowSet { SqlRows(const xmlpp::Element * p); ~SqlRows(); - void execute(const RowProcessor *) const; + void execute(const Glib::ustring &, const RowProcessor *) const; virtual void loadComplete(const CommonObjects *); - virtual void setFilter(const Glib::ustring &); - unsigned int columnCount() const; - const Glib::ustring & getColumnName(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; const Variable dataSource; @@ -80,7 +73,14 @@ class SqlRows : public RowSet { }; SqlCommand sqlCommand; typedef boost::shared_ptr SelectPtr; - mutable SelectPtr query; + class SqlState : public RowState { + public: + SqlState(SelectPtr query); + const Columns & getColumns() const; + SelectPtr query; + mutable Columns columns; + friend class SqlRows; + }; const RdbmsDataSource * db; }; diff --git a/project2/streamRows.cpp b/project2/streamRows.cpp index 825dc60..98d7f03 100644 --- a/project2/streamRows.cpp +++ b/project2/streamRows.cpp @@ -2,7 +2,8 @@ #include "rowProcessor.h" StreamRows::StreamRows(const xmlpp::Element * p) : - DefinedColumns(p), + DefinedColumns(p, "columns/column", boost::bind(&Column::make, _1, _2)), + RowSet(p), fieldSep(p->get_attribute_value("fieldSep")[0]), quoteChar(p->get_attribute_value("quoteChar")[0]), keepBlankRows(p->get_attribute_value("keepBlankRows") == "true"), @@ -10,11 +11,8 @@ StreamRows::StreamRows(const xmlpp::Element * p) : newline(p->get_attribute_value("newline")), newlin(newline, 0, newline.length() - 1), encoding(p->get_attribute_value("encoding")), - skipheader(atoi(p->get_attribute_value("skipheader").c_str())), - inQuotes(false), - prevWasQuote(false) + skipheader(atoi(p->get_attribute_value("skipheader").c_str())) { - mkCols = columns.empty(); } StreamRows::~StreamRows() @@ -22,113 +20,85 @@ StreamRows::~StreamRows() } void -StreamRows::addColumn(Glib::ustring & tok) const -{ - for (Glib::ustring::iterator i = tok.begin(); i != tok.end(); ) { - if (!isalnum(*i)) { - tok.erase(i); - } - else { - i++; - } - } - columns.insert(Column(columns.size(), tok)); -} - -void -StreamRows::begin() const -{ - curCol = columns.get().begin(); - tok.clear(); -} - -void -StreamRows::pushChar(gunichar c, const RowProcessor * rp) const +StreamRows::pushChar(gunichar c, ParseState & ps) const { - if ((!inQuotes) && (c == *newline.rbegin()) && (tok.compare(tok.length() - newlin.length(), newlin.length(), newlin) == 0)) { + if ((!ps.inQuotes) && (c == *newline.rbegin()) && (ps.tok.compare(ps.tok.length() - newlin.length(), newlin.length(), newlin) == 0)) { if (skipheader) { - skipheader -= 1; + ps.skipheader -= 1; } else { - tok.erase(tok.length() - newlin.length()); - if (!mkCols) { - if (!tok.empty()) { - *curCol++ = VariableType(tok); - } - if (keepBlankRows || curCol != columns.get().begin()) { - while (curCol != columns.get().end()) { - *curCol++ = curCol->defValue; - } - rp->rowReady(); - rowNum += 1; - } - else if (countBlankRows) { - rowNum += 1; - } + ps.tok.erase(ps.tok.length() - newlin.length()); + if (!ps.tok.empty()) { + *ps.curCol++ = VariableType(ps.tok); } - else { - if (!tok.empty()) { - addColumn(tok); + if (keepBlankRows || ps.curCol != ps.fields.begin()) { + while (ps.curCol != ps.fields.end()) { + *ps.curCol++ = Null(); } - mkCols = false; + ps.process(ps.rp); } - curCol = columns.get().begin(); + else if (countBlankRows) { + ps.blankRow(); + } + ps.curCol = ps.fields.begin(); } - tok.clear(); + ps.tok.clear(); } else if (c == quoteChar) { - if (prevWasQuote) { - tok += c; - prevWasQuote = false; - inQuotes = !inQuotes; + if (ps.prevWasQuote) { + ps.tok += c; + ps.prevWasQuote = false; + ps.inQuotes = !ps.inQuotes; } else { - prevWasQuote = inQuotes; - inQuotes = !inQuotes; + ps.prevWasQuote = ps.inQuotes; + ps.inQuotes = !ps.inQuotes; } } - else if ((!inQuotes) && (c == fieldSep)) { - prevWasQuote = false; + else if ((!ps.inQuotes) && (c == fieldSep)) { + ps.prevWasQuote = false; if (skipheader == 0) { - if (mkCols) { - addColumn(tok); - } - else { - *curCol++ = VariableType(tok); - } + *ps.curCol++ = VariableType(ps.tok); } - tok.clear(); + ps.tok.clear(); } else { - prevWasQuote = false; - tok += c; + ps.prevWasQuote = false; + ps.tok += c; } } +StreamRows::ParseState::ParseState(const StreamRows * rows, const RowProcessor * proc) : + ColumnValues(rows), + sr(rows), + rp(proc), + inQuotes(false), + prevWasQuote(false), + curCol(fields.begin()) +{ +} + +StreamRows::ParseState::~ParseState() +{ + sr->end(*this); +} + void -StreamRows::end(const RowProcessor * rp) const +StreamRows::end(ParseState & ps) const { - if (!tok.empty()) { + if (!ps.tok.empty()) { if (skipheader == 0) { - if (mkCols) { - addColumn(tok); - } - else { - *curCol++ = VariableType(tok); - } + *ps.curCol++ = VariableType(ps.tok); } } - if (keepBlankRows || curCol != columns.get().begin()) { - while (curCol != columns.get().end()) { - *curCol++ = curCol->defValue; + if (keepBlankRows || ps.curCol != ps.fields.begin()) { + while (ps.curCol != ps.fields.end()) { + *ps.curCol++ = Null(); } - rp->rowReady(); - rowNum += 1; + ps.process(ps.rp); } else if (countBlankRows) { - rowNum += 1; + ps.blankRow(); } - curCol = columns.get().begin(); - tok.clear(); } diff --git a/project2/streamRows.h b/project2/streamRows.h index 4dd9064..2d10116 100644 --- a/project2/streamRows.h +++ b/project2/streamRows.h @@ -7,18 +7,29 @@ class RowProcessor; /// Base class for Project2 components that create a row set based on the contents of a byte stream -class StreamRows : public DefinedColumns { +class StreamRows : public DefinedColumns, public RowSet { public: StreamRows(const xmlpp::Element * p); ~StreamRows(); protected: - void begin() const; - void pushChar(gunichar ch, const RowProcessor *) const; - void end(const RowProcessor *) const; - - private: - void addColumn(Glib::ustring & rawtok) const; + class ParseState : public ColumnValues { + public: + ParseState(const StreamRows *, const RowProcessor *); + ~ParseState(); + + const StreamRows * sr; + const RowProcessor * rp; + size_t skipheader; + bool inQuotes; + bool prevWasQuote; + Glib::ustring tok; + FieldValues::iterator curCol; + + friend class StreamRows; + }; + void pushChar(gunichar ch, ParseState &) const; + void end(ParseState &) const; public: const gunichar fieldSep; @@ -28,13 +39,7 @@ class StreamRows : public DefinedColumns { const Glib::ustring newline; const Glib::ustring newlin; const std::string encoding; - // Used in callback - mutable size_t skipheader; - mutable bool mkCols; - mutable bool inQuotes; - mutable bool prevWasQuote; - mutable Glib::ustring tok; - mutable Columns::index::type::iterator curCol; + const size_t skipheader; }; #endif diff --git a/project2/tablepatch.cpp b/project2/tablepatch.cpp index aacedbb..f87f60e 100644 --- a/project2/tablepatch.cpp +++ b/project2/tablepatch.cpp @@ -6,6 +6,8 @@ #include #include +using namespace DB; + TablePatch::TablePatch(const Connection & wdb, const TablePatch::Table & s, const TablePatch::Table & d, const TablePatch::Columns & c) : src(s), diff --git a/project2/tablepatch.h b/project2/tablepatch.h index 7352635..0174294 100644 --- a/project2/tablepatch.h +++ b/project2/tablepatch.h @@ -8,8 +8,6 @@ #include #include -using namespace DB; - class TablePatch { public: typedef std::string Table; @@ -23,7 +21,7 @@ class TablePatch { const char * what() const throw(); }; - TablePatch(const Connection & db, const Table & src, const Table & dest, const Columns & cols); + TablePatch(const DB::Connection & db, const Table & src, const Table & dest, const Columns & cols); void addKey(const Column & col); void patch(const char * where, const char * order); @@ -37,7 +35,7 @@ class TablePatch { Table dest; PrimaryKey pk; Columns cols; - const Connection &db; + const DB::Connection &db; }; #endif diff --git a/project2/urlRows.cpp b/project2/urlRows.cpp index 5669925..f8f7eed 100644 --- a/project2/urlRows.cpp +++ b/project2/urlRows.cpp @@ -24,27 +24,21 @@ UrlRows::loadComplete(const CommonObjects *) { } -void -UrlRows::setFilter(const Glib::ustring &) -{ - throw NotSupported(__PRETTY_FUNCTION__); -} - size_t UrlRows::handleDataHelper(const char * ptr, size_t size, size_t nmemb, void *stream) { const callback * cb = static_cast(stream); - size_t used = cb->urlRows->handleData(cb->rp, ptr, size * nmemb); + size_t used = cb->urlRows->handleData(cb->ps, ptr, size * nmemb); return used; } size_t -UrlRows::handleData(const RowProcessor * rp, const char * bytes, size_t bytesLen) const +UrlRows::handleData(ParseState & ps, const char * bytes, size_t bytesLen) const { size_t used = 0, len = 0; const gchar * utf8 = convertRequired ? g_convert(bytes, bytesLen, "utf-8", encoding.c_str(), &used, &len, NULL) : bytes; for (const gchar * iter = utf8; *iter; iter = g_utf8_next_char(iter)) { - this->pushChar(*iter, rp); + this->pushChar(*iter, ps); } if (convertRequired) { // We allocated it.. sooo.... @@ -57,21 +51,19 @@ UrlRows::handleData(const RowProcessor * rp, const char * bytes, size_t bytesLen } void -UrlRows::execute(const RowProcessor * rp) const +UrlRows::execute(const Glib::ustring &, const RowProcessor * rp) const { - rowNum = 1; - begin(); CurlHandle::Ptr c = newCurl(); callback cb(this, rp); c->setopt(CURLOPT_WRITEDATA, &cb); c->setopt(CURLOPT_WRITEFUNCTION, &handleDataHelper); c->perform(); - end(rp); } UrlRows::callback::callback(const UrlRows * u, const RowProcessor * r) : urlRows(u), - rp(r) + rp(r), + ps(u, r) { } diff --git a/project2/urlRows.h b/project2/urlRows.h index ca1894d..98273bd 100644 --- a/project2/urlRows.h +++ b/project2/urlRows.h @@ -15,17 +15,17 @@ class UrlRows : public StreamRows, CurlHelper { ~UrlRows(); virtual void loadComplete(const CommonObjects *); - void execute(const RowProcessor *) const; - virtual void setFilter(const Glib::ustring &); + void execute(const Glib::ustring &, const RowProcessor *) const; private: struct callback { callback(const UrlRows * urlRows, const RowProcessor * rp); const UrlRows * urlRows; const RowProcessor * rp; + mutable ParseState ps; }; static size_t handleDataHelper(const char * ptr, size_t size, size_t nmemb, void * stream); - size_t handleData(const RowProcessor * rp, const char * bytes, size_t bytesLen) const; + size_t handleData(ParseState &, const char * bytes, size_t bytesLen) const; bool convertRequired; }; diff --git a/project2/variables-modlookup.cpp b/project2/variables-modlookup.cpp index 24c4167..6ba489a 100644 --- a/project2/variables-modlookup.cpp +++ b/project2/variables-modlookup.cpp @@ -84,24 +84,20 @@ class VariableLookup : public VariableImplDyn, public RowProcessor { void fillCache() const { BOOST_FOREACH(const RowSets::value_type & rs, rowSets) { - cs = rs; - rs->execute(this); + rs->execute(filter, this); } - cs.reset(); Logger()->messagef(LOG_DEBUG, "%s: %s has filled cached with %zu items", __PRETTY_FUNCTION__, name.c_str(), map.size()); } - void rowReady() const + void rowReady(const RowState * rs) const { Key k; - k.reserve(cs->columnCount() - 1); BOOST_FOREACH(const Parameters::value_type & p, parameters) { - k.push_back(cs->getCurrentValue(p.first)); + k.push_back(rs->getCurrentValue(p.first)); } - map[k] = cs->getCurrentValue(name); + map[k] = rs->getCurrentValue(name); } mutable Map map; - mutable RowSetPtr cs; typedef ANONSTORAGEOF(RowSet) RowSets; RowSets rowSets; const Glib::ustring name; diff --git a/project2/variables.cpp b/project2/variables.cpp index 516e187..70f51b8 100644 --- a/project2/variables.cpp +++ b/project2/variables.cpp @@ -166,13 +166,10 @@ class VariableParent : public VariableImplDyn { { try { if (!getValue) { - RowSet::RowValuesStack::const_reverse_iterator r = RowSet::Stack().rbegin(); - for (size_t p = depth; p--; r++) ; - if (r == RowSet::Stack().rend()) { + if (depth > RowState::Stack().size()) { throw RowSet::ParentOutOfRange(depth); } - ; - bind(*r); + bind(RowState::Stack()[RowState::Stack().size() - depth]); } return getValue(); } @@ -190,14 +187,13 @@ class VariableParent : public VariableImplDyn { } } protected: - void bind(ConstRowSetPtr row) const + void bind(const RowState * row) const { if (attr) { getValue = boost::bind(row->resolveAttr(name)); } else { - typedef VariableType (RowSet::*gCV)(const Glib::ustring &) const; - getValue = boost::bind((gCV)&RowSet::getCurrentValue, row, name); + getValue = boost::bind(&RowState::getCurrentValue, row, name); } } const size_t depth; diff --git a/project2/xmlRows.cpp b/project2/xmlRows.cpp index bd958a5..8982945 100644 --- a/project2/xmlRows.cpp +++ b/project2/xmlRows.cpp @@ -25,6 +25,7 @@ XmlRows::XmlRows(const xmlpp::Element * p) : boost::split(root, recordRoot, boost::is_any_of("/")); boost::split(trigger, recordTrigger, boost::is_any_of("/")); + unsigned int col = 0; BOOST_FOREACH(const xmlpp::Node * node, p->find("fields/field")) { const xmlpp::Element * elem = dynamic_cast(node); if (elem) { @@ -38,12 +39,10 @@ XmlRows::XmlRows(const xmlpp::Element * p) : p.push_back(Glib::ustring(It->begin(), It->end())); } - fields[p] = elem->get_attribute_value("name"); + fields[p] = col; + fieldNames.insert(new Column(col++, elem->get_attribute_value("name"))); } } - BOOST_FOREACH(const Interests::value_type & v, fields) { - fieldNames.push_back(v.second); - } } XmlRows::~XmlRows() @@ -55,58 +54,9 @@ XmlRows::loadComplete(const CommonObjects *) { } +static void -XmlRows::setFilter(const Glib::ustring &) -{ - throw NotSupported(__PRETTY_FUNCTION__); -} - -VariableType -XmlRows::getCurrentValue(const Glib::ustring & id) const -{ - Values::const_iterator i = values.find(id); - if (i == values.end()) { - throw FieldDoesNotExist(id); - } - return i->second; -} - -VariableType -XmlRows::getCurrentValue(unsigned int col) const -{ - Values::const_iterator i = values.find(fieldNames[col]); - if (i == values.end()) { - throw FieldDoesNotExist(""); - } - return i->second; -} - -bool -XmlRows::isNull(unsigned int col) const -{ - return (values.find(fieldNames[col]) == values.end()); -} - -bool -XmlRows::isNull(const Glib::ustring & col) const -{ - return (values.find(col) == values.end()); -} - -unsigned int -XmlRows::columnCount() const -{ - return fields.size(); -} - -const Glib::ustring & -XmlRows::getColumnName(unsigned int col) const -{ - return fieldNames[col]; -} - -void -store(const XmlRows::Path & position, XmlRows::Values & values, const XmlRows::Interests & fields, const xmlChar * val) +store(const XmlRows::Path & position, RowState::FieldValues & values, const XmlRows::Interests & fields, const xmlChar * val) { XmlRows::Interests::const_iterator i = fields.find(position); if (i != fields.end()) { @@ -115,14 +65,14 @@ store(const XmlRows::Path & position, XmlRows::Values & values, const XmlRows::I } void -XmlRows::execute(const RowProcessor * rp) const +XmlRows::execute(const Glib::ustring &, const RowProcessor * rp) const { - rowNum = 1; xmlTextReaderPtr reader = xmlReaderForFile(filename.c_str(), NULL, 0); if (reader == NULL) { throw std::runtime_error("Failed to open file"); } + XmlState xs(this); Path position; bool enableCapture = false; while (xmlTextReaderRead(reader) == 1) { @@ -138,16 +88,15 @@ XmlRows::execute(const RowProcessor * rp) const std::string attr("@"); attr += (const char *)xmlTextReaderConstName(reader); p.push_back(attr); - store(p, values, fields, xmlTextReaderConstValue(reader)); + store(p, xs.fields, fields, xmlTextReaderConstValue(reader)); } } if (empty) { if (position == trigger) { - rp->rowReady(); - rowNum += 1; + xs.process(rp, false); } if (position == root) { - values.clear(); + xs.reset(); } position.pop_back(); } @@ -155,17 +104,16 @@ XmlRows::execute(const RowProcessor * rp) const break; case XML_READER_TYPE_TEXT: if (enableCapture) { - store(position, values, fields, xmlTextReaderConstValue(reader)); + store(position, xs.fields, fields, xmlTextReaderConstValue(reader)); } break; case XML_READER_TYPE_END_ELEMENT: if (enableCapture) { if (position == trigger) { - rp->rowReady(); - rowNum += 1; + xs.process(rp, false); } if (position == root) { - values.clear(); + xs.reset(); } } position.pop_back(); @@ -176,3 +124,13 @@ XmlRows::execute(const RowProcessor * rp) const xmlCleanupParser(); } +XmlRows::XmlState::XmlState(const XmlRows * rows) : + rs(rows) +{ +} +const Columns & +XmlRows::XmlState::getColumns() const +{ + return rs->fieldNames; +} + diff --git a/project2/xmlRows.h b/project2/xmlRows.h index efbaf5e..3ab889e 100644 --- a/project2/xmlRows.h +++ b/project2/xmlRows.h @@ -9,35 +9,32 @@ /// Project2 component to create a row set based on the contents of an XML file class XmlRows : public RowSet { public: - typedef std::map Values; typedef std::vector Path; - typedef std::map Interests; + typedef std::map Interests; XmlRows(const xmlpp::Element * p); ~XmlRows(); - void execute(const RowProcessor *) const; + void execute(const Glib::ustring &, const RowProcessor *) const; virtual void loadComplete(const CommonObjects *); - virtual void setFilter(const Glib::ustring &); - unsigned int columnCount() const; - const Glib::ustring & getColumnName(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; const Glib::ustring recordRoot; const Glib::ustring recordTrigger; const std::string filename; private: - mutable Values values; + class XmlState : public RowState { + public: + XmlState(const XmlRows *); + const Columns & getColumns() const; + const XmlRows * rs; + }; Path root; Path trigger; Interests fields; bool anyInterestingAttributes; - std::vector fieldNames; + Columns fieldNames; }; #endif diff --git a/project2/xslRows.cpp b/project2/xslRows.cpp index 999f196..07d57b6 100644 --- a/project2/xslRows.cpp +++ b/project2/xslRows.cpp @@ -1,4 +1,5 @@ #include "xslRows.h" +#include "safeMapFind.h" #include "rowProcessor.h" #include "logger.h" #include "xml.h" @@ -46,16 +47,6 @@ XslRows::loadComplete(const CommonObjects *) { } -void -XslRows::setFilter(const Glib::ustring & f) -{ - FilterViews::const_iterator i = fvs.find(f); - if (i == fvs.end()) { - throw FilterNotFound(f); - } - fv = i->second; -} - bool XslRows::asHtml() const { @@ -75,8 +66,10 @@ XslRows::newCurl() const } void -XslRows::execute(const RowProcessor * rp) const +XslRows::execute(const Glib::ustring & filter, const RowProcessor * rp) const { + FilterViewPtr fv = safeMapFind(fvs, filter)->second; + typedef boost::shared_ptr xmlXPathObjectSPtr; typedef boost::shared_ptr xmlXPathContextSPtr; xmlDocPtr doc = getDocument(url(), encoding()); @@ -91,16 +84,15 @@ XslRows::execute(const RowProcessor * rp) const if (!xpathObj || !xpathObj->nodesetval) { throw XpathEvalError(xmlGetLastError()->message); } - rowNum = 1; Logger()->messagef(LOG_INFO, "%d nodes matched %s", xpathObj->nodesetval->nodeNr, (const char *)(fv->root())); + XslState xs(fv); for (int row = 0; row < xpathObj->nodesetval->nodeNr; row += 1) { xmlNodePtr rowRoot = xpathObj->nodesetval->nodeTab[row]; xpathCtx->node = rowRoot; - values.clear(); - BOOST_FOREACH(const FilterView::XPaths::value_type & xp, fv->xpaths) { - VariableType path(xp.second()); + BOOST_FOREACH(const Columns::value_type & _xp, fv->columns.get()) { + const FilterViewColumn * xp = static_cast(_xp.get()); + const VariableType & path(xp->path); if (boost::get(&path)) { - values[xp.first] = Null(); continue; } xmlXPathObjectSPtr xpathObjI = xmlXPathObjectSPtr(xmlXPathEvalExpression(path, xpathCtx.get()), xmlXPathFreeObject); @@ -108,10 +100,10 @@ XslRows::execute(const RowProcessor * rp) const throw XpathEvalError(xmlGetLastError()->message); } if (xpathObjI->floatval) { - values[xp.first] = xpathObjI->floatval; + xs.fields[xp->idx] = xpathObjI->floatval; } else if (xpathObjI->stringval) { - values[xp.first] = Glib::ustring((const char *)xpathObjI->stringval); + xs.fields[xp->idx] = Glib::ustring((const char *)xpathObjI->stringval); } else if (xpathObjI->nodesetval) { Glib::ustring str; @@ -127,64 +119,41 @@ XslRows::execute(const RowProcessor * rp) const } } } - values[xp.first] = str; - } - else { - values[xp.first] = Null(); + xs.fields[xp->idx] = str; } } - rp->rowReady(); - rowNum += 1; + xs.process(rp); } } XslRows::FilterView::FilterView(const xmlpp::Element * p) : + DefinedColumns(p, "field", boost::bind(XslRows::FilterViewColumn::make, _1, _2)), name(p->get_attribute_value("name")), 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"), Variable(elem, "xpath"))); - } - } } -VariableType -XslRows::getCurrentValue(const Glib::ustring & id) const +XslRows::FilterViewColumn::FilterViewColumn(unsigned int idx, const xmlpp::Element * p) : + Column(idx, p), + path(p, "xpath") { - return values.find(id)->second; } -VariableType -XslRows::getCurrentValue(unsigned int col) const -{ - return getCurrentValue(getColumnName(col)); -} - -bool -XslRows::isNull(unsigned int col) const -{ - return isNull(getColumnName(col)); -} - -bool -XslRows::isNull(const Glib::ustring & col) const +XslRows::FilterViewColumn * +XslRows::FilterViewColumn::make(unsigned int idx, const xmlpp::Element * p) { - return (values.find(col) == values.end()); + return new FilterViewColumn(idx, p); } -unsigned int -XslRows::columnCount() const +XslRows::XslState::XslState(FilterViewCPtr f) : + fv(f) { - return fv->xpaths.size(); + fields.resize(f->columns.size()); } -const Glib::ustring & -XslRows::getColumnName(unsigned int col) const +const Columns & +XslRows::XslState::getColumns() const { - FilterView::XPaths::const_iterator i = fv->xpaths.begin(); - while (col--) i++; - return i->first; + return fv->columns; } diff --git a/project2/xslRows.h b/project2/xslRows.h index a30ca02..e33932f 100644 --- a/project2/xslRows.h +++ b/project2/xslRows.h @@ -9,6 +9,7 @@ #include "variables.h" #include "xslRowsCache.h" #include "curlHelper.h" +#include "definedColumns.h" /// Project2 component to create a row set based on the contents of an XML resource and specific XPaths with its hierarchy class XslRows : public RowSet, XslRowsCache, CurlHelper { @@ -16,21 +17,20 @@ class XslRows : public RowSet, XslRowsCache, CurlHelper { XslRows(const xmlpp::Element * p); ~XslRows(); - void execute(const RowProcessor *) const; + void execute(const Glib::ustring &, const RowProcessor *) const; virtual void loadComplete(const CommonObjects *); - virtual void setFilter(const Glib::ustring &); - unsigned int columnCount() const; - const Glib::ustring & getColumnName(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; const bool html; const bool warnings; private: - class FilterView : public virtual IntrusivePtrBase { + class FilterViewColumn : public Column { + public: + FilterViewColumn(unsigned int, const xmlpp::Element *); + static FilterViewColumn * make(unsigned int, const xmlpp::Element *); + const Variable path; + }; + class FilterView : public DefinedColumns, public virtual IntrusivePtrBase { public: typedef std::map XPaths; @@ -38,21 +38,25 @@ class XslRows : public RowSet, XslRowsCache, CurlHelper { const Glib::ustring name; const Variable root; - XPaths xpaths; }; typedef boost::intrusive_ptr FilterViewPtr; + typedef boost::intrusive_ptr FilterViewCPtr; typedef std::map FilterViews; FilterViews fvs; - FilterViewPtr fv; virtual CurlHandle::Ptr newCurl() const; virtual bool asHtml() const; virtual bool withWarnings() const; typedef std::map Namespaces; - mutable Namespaces namespaces; - typedef std::map Values; - mutable Values values; + Namespaces namespaces; + class XslState : public RowState { + public: + XslState(FilterViewCPtr); + const Columns & getColumns() const; + private: + const FilterViewCPtr fv; + }; const Variable encoding; }; -- cgit v1.2.3