diff options
| -rw-r--r-- | project2/appEngine.cpp | 8 | ||||
| -rw-r--r-- | project2/appEngine.h | 7 | ||||
| -rw-r--r-- | project2/cgiAppEngine.cpp | 11 | ||||
| -rw-r--r-- | project2/cgiAppEngine.h | 4 | ||||
| -rw-r--r-- | project2/iHaveParameters.cpp | 3 | ||||
| -rw-r--r-- | project2/iHaveParameters.h | 4 | ||||
| -rw-r--r-- | project2/iterate.cpp | 12 | ||||
| -rw-r--r-- | project2/paramChecker.cpp | 1 | ||||
| -rw-r--r-- | project2/paramChecker.h | 2 | ||||
| -rw-r--r-- | project2/perRowValues.cpp | 28 | ||||
| -rw-r--r-- | project2/perRowValues.h | 11 | ||||
| -rw-r--r-- | project2/regexCheck.cpp | 3 | ||||
| -rw-r--r-- | project2/regexCheck.h | 1 | ||||
| -rw-r--r-- | project2/sessionClearTask.cpp | 3 | ||||
| -rw-r--r-- | project2/sessionSetTask.cpp | 16 | ||||
| -rw-r--r-- | project2/sessionSetTask.h | 5 | ||||
| -rw-r--r-- | project2/sqlCheck.cpp | 7 | ||||
| -rw-r--r-- | project2/sqlIterate.cpp | 23 | ||||
| -rw-r--r-- | project2/sqlIterate.h | 2 | ||||
| -rw-r--r-- | project2/sqlTask.cpp | 16 | ||||
| -rw-r--r-- | project2/sqlView.cpp | 22 | ||||
| -rw-r--r-- | project2/sqlView.h | 2 | ||||
| -rw-r--r-- | project2/variables.cpp | 148 | ||||
| -rw-r--r-- | project2/variables.h | 37 | ||||
| -rw-r--r-- | project2/view.cpp | 12 | 
25 files changed, 284 insertions, 104 deletions
diff --git a/project2/appEngine.cpp b/project2/appEngine.cpp index 632bb11..be49c10 100644 --- a/project2/appEngine.cpp +++ b/project2/appEngine.cpp @@ -1,10 +1,18 @@  #include "appEngine.h" +#include <stdexcept> + +ApplicationEngine * ApplicationEngine::currentEngine = NULL;  ApplicationEngine::ApplicationEngine(const Environment *)  { +	if (currentEngine) { +		throw std::runtime_error("One application at a time, please"); +	} +	currentEngine = this;  }  ApplicationEngine::~ApplicationEngine()  { +	currentEngine = NULL;  } diff --git a/project2/appEngine.h b/project2/appEngine.h index d2cff10..59e0d4d 100644 --- a/project2/appEngine.h +++ b/project2/appEngine.h @@ -3,6 +3,7 @@  #include "environment.h"  #include "dataSource.h" +#include "session.h"  class ApplicationEngine {  	public: @@ -14,8 +15,7 @@ class ApplicationEngine {  		virtual void process() const = 0;  		virtual const Environment * env() const = 0; -		virtual void SessionSet(const Glib::ustring & name, const Glib::ustring & value) const = 0; -		virtual void SessionClear(const Glib::ustring & name) const = 0; +		virtual SessionPtr session() const = 0;  		template <class DataSourceType>  		const DataSourceType * dataSource(const std::string & name) const @@ -30,8 +30,11 @@ class ApplicationEngine {  			}  			return s;  		} +		static ApplicationEngine * getCurrent() { return currentEngine; }  	protected:  		mutable DataSources datasources; +	private: +		static ApplicationEngine * currentEngine;  };  #endif diff --git a/project2/cgiAppEngine.cpp b/project2/cgiAppEngine.cpp index 60b1ed3..a419be0 100644 --- a/project2/cgiAppEngine.cpp +++ b/project2/cgiAppEngine.cpp @@ -185,14 +185,9 @@ CgiApplicationEngine::RequestStage::run()  	return new PresentStage(appEngine, present);  } -void -CgiApplicationEngine::SessionSet(const Glib::ustring & name, const Glib::ustring & value) const -{ -	sessionsContainer->GetSession(sessionID)->SetValue(name, value); -} -void -CgiApplicationEngine::SessionClear(const Glib::ustring & name) const +SessionPtr +CgiApplicationEngine::session() const  { -	sessionsContainer->GetSession(sessionID)->ClearValue(name); +	return sessionsContainer->GetSession(sessionID);  } diff --git a/project2/cgiAppEngine.h b/project2/cgiAppEngine.h index f6f37d0..0172eee 100644 --- a/project2/cgiAppEngine.h +++ b/project2/cgiAppEngine.h @@ -10,6 +10,7 @@  #include <libxml++/parsers/domparser.h>  class CgiEnvironment; +class Session;  namespace cgicc {  	class HTTPContentHeader;  } @@ -26,8 +27,7 @@ class CgiApplicationEngine : public ApplicationEngine {  			w(doc->cobj());  		}  		const Environment * env() const; -		virtual void SessionSet(const Glib::ustring & name, const Glib::ustring & value) const; -		virtual void SessionClear(const Glib::ustring & name) const; +		SessionPtr session() const;  		const CgiEnvironment * _env;  	protected:  		cgicc::HTTPContentHeader * header; diff --git a/project2/iHaveParameters.cpp b/project2/iHaveParameters.cpp index c13eddf..0f1084e 100644 --- a/project2/iHaveParameters.cpp +++ b/project2/iHaveParameters.cpp @@ -18,8 +18,7 @@ IHaveParameters::~IHaveParameters()  }  IHaveParameters::_Parameter::_Parameter(const xmlpp::Element * p) : -	source(p->get_attribute_value("source")), -	id(p->get_attribute_value("id")), +	value(p->get_attribute("value")),  	bind(atoi(p->get_attribute_value("bind").c_str()))  {  } diff --git a/project2/iHaveParameters.h b/project2/iHaveParameters.h index 31c597a..329e341 100644 --- a/project2/iHaveParameters.h +++ b/project2/iHaveParameters.h @@ -3,14 +3,14 @@  #include <libxml++/nodes/element.h>  #include <boost/shared_ptr.hpp> +#include "variables.h"  class IHaveParameters {  	public:  		class _Parameter {  			public:  				_Parameter(const xmlpp::Element * p); -				const std::string source; -				const std::string id; +				const Variable value;  				const unsigned int bind;  		};  		IHaveParameters(const xmlpp::Element * p); diff --git a/project2/iterate.cpp b/project2/iterate.cpp index 02fc149..843d598 100644 --- a/project2/iterate.cpp +++ b/project2/iterate.cpp @@ -34,8 +34,16 @@ _Iterate::AddLoaders(Loaders & l, NoOutputExecutes & iterates)  void  _Iterate::executeChildren(const ApplicationEngine * ep, const PerRowValues * parent) const  { -	BOOST_FOREACH(NoOutputExecutes::value_type sq, subIterates) { -		sq.second->execute(ep, this); +	try { +		PerRowValues::beginRow(this); +		BOOST_FOREACH(NoOutputExecutes::value_type sq, subIterates) { +			sq.second->execute(ep, this); +		} +		PerRowValues::endRow(this); +	} +	catch (...) { +		PerRowValues::endRow(this); +		throw;  	}  } diff --git a/project2/paramChecker.cpp b/project2/paramChecker.cpp index 627f1be..5455f22 100644 --- a/project2/paramChecker.cpp +++ b/project2/paramChecker.cpp @@ -7,7 +7,6 @@  _ParamChecker::_ParamChecker(const xmlpp::Element * p) :  	_SourceObject(p),  	message(xmlChildText(p, "message")), -	applyTo(p->get_attribute_value("apply-to")),  	present(p->get_attribute_value("present"))  {  } diff --git a/project2/paramChecker.h b/project2/paramChecker.h index 1ffe89f..b22a1f9 100644 --- a/project2/paramChecker.h +++ b/project2/paramChecker.h @@ -6,6 +6,7 @@  #include <map>  #include "sourceObject.h"  #include "xmlObjectLoader.h" +#include "variables.h"  class ApplicationEngine;  class _ParamChecker; @@ -21,7 +22,6 @@ class _ParamChecker : public virtual _SourceObject {  		virtual bool performCheck(const ApplicationEngine *) const = 0;  		const Glib::ustring message; -		const std::string applyTo;  		const std::string present;  		static void AddLoaders(Loaders & l, OrderedParamCheckers & vs); diff --git a/project2/perRowValues.cpp b/project2/perRowValues.cpp new file mode 100644 index 0000000..30433fd --- /dev/null +++ b/project2/perRowValues.cpp @@ -0,0 +1,28 @@ +#include "perRowValues.h" +#include <cstdlib> + +PerRowValues::RowValuesStack PerRowValues::stack; + +PerRowValues::PerRowValues() +{ +} + +PerRowValues::~PerRowValues() +{ +} + +void +PerRowValues::beginRow(const PerRowValues * r) +{ +	stack.push_back(r); +} + +void +PerRowValues::endRow(const PerRowValues * r) +{ +	if ((*stack.rbegin()) != r) { +		std::abort(); +	} +	stack.pop_back(); +} + diff --git a/project2/perRowValues.h b/project2/perRowValues.h index 2a46763..eec8e37 100644 --- a/project2/perRowValues.h +++ b/project2/perRowValues.h @@ -2,10 +2,21 @@  #define PERROWVALUES_H  #include <glibmm/ustring.h> +#include <vector>  class PerRowValues {  	public: +		typedef std::vector<const PerRowValues *> RowValuesStack; +		PerRowValues(); +		virtual ~PerRowValues() = 0; +  		virtual Glib::ustring getCurrentValue(const Glib::ustring & id) const = 0; +		static const RowValuesStack & Stack() { return stack; } +		static void beginRow(const PerRowValues * r); +		static void endRow(const PerRowValues * r); + +	private: +		static RowValuesStack stack;  };  #endif diff --git a/project2/regexCheck.cpp b/project2/regexCheck.cpp index 672194f..d6e1bb0 100644 --- a/project2/regexCheck.cpp +++ b/project2/regexCheck.cpp @@ -6,6 +6,7 @@  _RegexCheck::_RegexCheck(const xmlpp::Element * p) :  	_SourceObject(p),  	_ParamChecker(p), +	applyTo(p->get_attribute("apply-to")),  	regex(xmlChildText(p, "regex").raw())  {  } @@ -17,7 +18,7 @@ _RegexCheck::~_RegexCheck()  bool  _RegexCheck::performCheck(const ApplicationEngine * ep) const  { -	const Glib::ustring & param = ep->env()->getParamQuery(applyTo); +	const Glib::ustring & param(applyTo);  	return boost::regex_match(param.begin(), param.end(), regex);  } diff --git a/project2/regexCheck.h b/project2/regexCheck.h index 5db92f5..b515d54 100644 --- a/project2/regexCheck.h +++ b/project2/regexCheck.h @@ -11,6 +11,7 @@ class _RegexCheck : public _ParamChecker {  		bool performCheck(const ApplicationEngine *) const; +		const Variable applyTo;  		const boost::regex regex;  };  typedef boost::shared_ptr<_RegexCheck> RegexCheck; diff --git a/project2/sessionClearTask.cpp b/project2/sessionClearTask.cpp index 963ebeb..696f250 100644 --- a/project2/sessionClearTask.cpp +++ b/project2/sessionClearTask.cpp @@ -2,6 +2,7 @@  #include "xmlObjectLoader.h"  #include "sessionClearTask.h"  #include "appEngine.h" +#include "session.h"  _SessionClearTask::_SessionClearTask(const xmlpp::Element * p) :  	_SourceObject(p), @@ -17,6 +18,6 @@ _SessionClearTask::~_SessionClearTask()  void  _SessionClearTask::execute(const ApplicationEngine * ep, const PerRowValues *) const  { -	ep->SessionClear(key); +	ep->session()->ClearValue(key);  } diff --git a/project2/sessionSetTask.cpp b/project2/sessionSetTask.cpp index abd02b0..8304494 100644 --- a/project2/sessionSetTask.cpp +++ b/project2/sessionSetTask.cpp @@ -3,12 +3,13 @@  #include "xmlObjectLoader.h"  #include "sessionSetTask.h"  #include "appEngine.h" +#include "session.h"  _SessionSetTask::_SessionSetTask(const xmlpp::Element * p) :  	_SourceObject(p),  	_Task(p), -	IHaveParameters(p), -	key(p->get_attribute_value("key")) +	key(p->get_attribute_value("key")), +	value(p->get_attribute("value"))  {  } @@ -19,15 +20,6 @@ _SessionSetTask::~_SessionSetTask()  void  _SessionSetTask::execute(const ApplicationEngine * ep, const PerRowValues * parent) const  { -	Parameter p = parameters.find(0)->second; -	if (p->source == "uri") { -		ep->SessionSet(key, ep->env()->getParamUri(p->id)); -	} -	else if (p->source == "parent") { -		ep->SessionSet(key, parent->getCurrentValue(p->id)); -	} -	else if (p->source == "query") { -		ep->SessionSet(key, ep->env()->getParamQuery(p->id)); -	} +	ep->session()->SetValue(key, value);  } diff --git a/project2/sessionSetTask.h b/project2/sessionSetTask.h index 32df37b..491c55d 100644 --- a/project2/sessionSetTask.h +++ b/project2/sessionSetTask.h @@ -7,19 +7,20 @@  #include "sourceObject.h"  #include "xmlObjectLoader.h"  #include "task.h" -#include "iHaveParameters.h" +#include "variables.h"  class ApplicationEngine;  class _SessionSetTask;  typedef boost::shared_ptr<_SessionSetTask> SessionSetTask; -class _SessionSetTask : public virtual _Task, public IHaveParameters { +class _SessionSetTask : public virtual _Task {  	public:  		_SessionSetTask(const xmlpp::Element * p);  		virtual ~_SessionSetTask();  		void execute(const ApplicationEngine *, const PerRowValues * parent = NULL) const;  		const Glib::ustring key; +		const Variable value;  };  #endif diff --git a/project2/sqlCheck.cpp b/project2/sqlCheck.cpp index 1dab147..65cf0e3 100644 --- a/project2/sqlCheck.cpp +++ b/project2/sqlCheck.cpp @@ -26,12 +26,7 @@ _SqlCheck::performCheck(const ApplicationEngine * ep) const  {  	ODBC::SelectCommand * query = new ODBC::SelectCommand(ep->dataSource<_RdbmsDataSource>(dataSource)->getReadonly(), sql);  	BOOST_FOREACH(Parameters::value_type p, parameters) { -		if (p.second->source == "uri") { -			query->bindParamS(p.second->bind, ep->env()->getParamUri(p.second->id)); -		} -		else if (p.second->source == "query") { -			query->bindParamS(p.second->bind, ep->env()->getParamQuery(p.second->id)); -		} +		query->bindParamS(p.second->bind, p.second->value);  	}  	bool retVal = false;  	while (query->fetch()) { diff --git a/project2/sqlIterate.cpp b/project2/sqlIterate.cpp index 90a8bc1..5499940 100644 --- a/project2/sqlIterate.cpp +++ b/project2/sqlIterate.cpp @@ -25,32 +25,11 @@ _SqlIterate::getCurrentValue(const Glib::ustring & id) const  	return (*query)[id].compose();  } -void -_SqlIterate::rebindCurrentValue(const Glib::ustring & id, ODBC::Command * cmd, unsigned int bind) const -{ -	(*query)[id].rebind(cmd, bind); -} -  void _SqlIterate::execute(const ApplicationEngine * ep, const PerRowValues * parent) const  { -	typedef std::map<std::string, xmlpp::Element *> Columns;  	query = new ODBC::SelectCommand(ep->dataSource<_RdbmsDataSource>(dataSource)->getReadonly(), sql);  	BOOST_FOREACH(Parameters::value_type p, parameters) { -		if (p.second->source == "uri") { -			query->bindParamS(p.second->bind, ep->env()->getParamUri(p.second->id)); -		} -		else if (p.second->source == "query") { -			query->bindParamS(p.second->bind, ep->env()->getParamQuery(p.second->id)); -		} -		else if (parent && p.second->source == "parent") { -			const _SqlIterate * psqlIterate = dynamic_cast<const _SqlIterate *>(parent); -			if (psqlIterate) { -				psqlIterate->rebindCurrentValue(p.second->id, query, p.second->bind); -			} -			else { -				query->bindParamS(p.second->bind, parent->getCurrentValue(p.second->id)); -			} -		} +		query->bindParamS(p.second->bind, p.second->value());  	}  	while (query->fetch()) {  		executeChildren(ep, this); diff --git a/project2/sqlIterate.h b/project2/sqlIterate.h index c9cef49..41b5648 100644 --- a/project2/sqlIterate.h +++ b/project2/sqlIterate.h @@ -18,7 +18,7 @@ class _SqlIterate : public IHaveParameters, public _Iterate {  		Glib::ustring getCurrentValue(const Glib::ustring & id) const;  		const std::string dataSource;  		const Glib::ustring sql; -		void rebindCurrentValue(const Glib::ustring & id, ODBC::Command *, unsigned int) const; +  	private:  		mutable ODBC::SelectCommand * query;  }; diff --git a/project2/sqlTask.cpp b/project2/sqlTask.cpp index e6fec24..3811b43 100644 --- a/project2/sqlTask.cpp +++ b/project2/sqlTask.cpp @@ -24,21 +24,7 @@ _SqlTask::execute(const ApplicationEngine * ep, const PerRowValues * parent) con  {  	ODBC::ModifyCommand modify(ep->dataSource<_RdbmsDataSource>(dataSource)->getWritable(), sql);  	BOOST_FOREACH(Parameters::value_type p, parameters) { -		if (p.second->source == "uri") { -			modify.bindParamS(p.second->bind, ep->env()->getParamUri(p.second->id)); -		} -		else if (p.second->source == "query") { -			modify.bindParamS(p.second->bind, ep->env()->getParamQuery(p.second->id)); -		} -		else if (parent && p.second->source == "parent") { -			const _SqlView * psqlview = dynamic_cast<const _SqlView *>(parent); -			if (psqlview) { -				psqlview->rebindCurrentValue(p.second->id, &modify, p.second->bind); -			} -			else { -				modify.bindParamS(p.second->bind, parent->getCurrentValue(p.second->id)); -			} -		} +		modify.bindParamS(p.second->bind, p.second->value);  	}  	modify.execute();  } diff --git a/project2/sqlView.cpp b/project2/sqlView.cpp index cab4ca5..41fa441 100644 --- a/project2/sqlView.cpp +++ b/project2/sqlView.cpp @@ -27,32 +27,12 @@ _SqlView::getCurrentValue(const Glib::ustring & id) const  	return (*query)[id].compose();  } -void -_SqlView::rebindCurrentValue(const Glib::ustring & id, ODBC::Command * cmd, unsigned int bind) const -{ -	(*query)[id].rebind(cmd, bind); -} -  void _SqlView::execute(xmlpp::Element * par, const ApplicationEngine * ep, const _View * parent) const  {  	typedef std::map<std::string, xmlpp::Element *> Columns;  	query = new ODBC::SelectCommand(ep->dataSource<_RdbmsDataSource>(dataSource)->getReadonly(), sql);  	BOOST_FOREACH(Parameters::value_type p, parameters) { -		if (p.second->source == "uri") { -			query->bindParamS(p.second->bind, ep->env()->getParamUri(p.second->id)); -		} -		else if (p.second->source == "query") { -			query->bindParamS(p.second->bind, ep->env()->getParamQuery(p.second->id)); -		} -		else if (parent && p.second->source == "parent") { -			const _SqlView * psqlview = dynamic_cast<const _SqlView *>(parent); -			if (psqlview) { -				psqlview->rebindCurrentValue(p.second->id, query, p.second->bind); -			} -			else { -				query->bindParamS(p.second->bind, parent->getCurrentValue(p.second->id)); -			} -		} +		query->bindParamS(p.second->bind, p.second->value);  	}  	xmlpp::Element * set = par->add_child(name);  	while (query->fetch()) { diff --git a/project2/sqlView.h b/project2/sqlView.h index 1a77e7d..5fd8a48 100644 --- a/project2/sqlView.h +++ b/project2/sqlView.h @@ -18,7 +18,7 @@ class _SqlView : public IHaveParameters, public _View {  		Glib::ustring getCurrentValue(const Glib::ustring & id) const;  		const std::string dataSource;  		const Glib::ustring sql; -		void rebindCurrentValue(const Glib::ustring & id, ODBC::Command *, unsigned int) const; +  	private:  		mutable ODBC::SelectCommand * query;  }; diff --git a/project2/variables.cpp b/project2/variables.cpp new file mode 100644 index 0000000..f8fe4bb --- /dev/null +++ b/project2/variables.cpp @@ -0,0 +1,148 @@ +#include "variables.h" +#include "appEngine.h" +#include "perRowValues.h" +#include "session.h" +#include <libxml++/nodes/textnode.h> +#include <stdexcept> +#include <boost/tokenizer.hpp> +#include <boost/foreach.hpp> + +class VariableLiteral : public VariableImpl { +	public: +		VariableLiteral(const Glib::ustring & src) : VariableImpl(src) { } + +		virtual const Glib::ustring & value() const { return source; } +}; + +class VariableImplDyn : public VariableImpl { +	public: +		VariableImplDyn(const Glib::ustring & src) : VariableImpl(src), cacheValid(false) { } +		virtual const Glib::ustring & value() const = 0; + +	protected: +		mutable Glib::ustring cache; +		mutable bool cacheValid; +}; + +class VariableSession : public VariableImplDyn { +	public: +		VariableSession(const Glib::ustring & src) : VariableImplDyn(src) { } +		const Glib::ustring & value() const +		{ +			if (!cacheValid) { +				cache = ApplicationEngine::getCurrent()->session()->GetValue(source.substr(1)); +				cacheValid = true; +			} +			return cache; +		} +}; + +class VariableParam : public VariableImplDyn { +	public: +		VariableParam(const Glib::ustring & src) : VariableImplDyn(src) { } +		const Glib::ustring & value() const +		{ +			if (!cacheValid) { +				cache = ApplicationEngine::getCurrent()->env()->getParamQuery(source.substr(1)); +				cacheValid = true; +			} +			return cache; +		} +}; + +class VariableUri : public VariableImplDyn { +	public: +		VariableUri(const Glib::ustring & src) : VariableImplDyn(src) { } +		const Glib::ustring & value() const +		{ +			if (!cacheValid) { +				cache = ApplicationEngine::getCurrent()->env()->getParamUri(source.substr(1)); +				cacheValid = true; +			} +			return cache; +		} +}; + +class VariableParent : public VariableImplDyn { +	public: +		VariableParent(const Glib::ustring & src) : VariableImplDyn(src) { } +		const Glib::ustring & value() const +		{ +			if (!cacheValid) { +				PerRowValues::RowValuesStack::const_iterator r = PerRowValues::Stack().end(); +				Glib::ustring::const_iterator c = source.begin(); +				while (*c == '^') { +					r--; +					c++; +				} +				cache = (*r)->getCurrentValue(Glib::ustring(c, source.end())); +				cacheValid = true; +			} +			return cache; +		} +}; + +class VariableParse : public VariableImplDyn { +	public: +		VariableParse(const Glib::ustring & src) : VariableImplDyn(src) { } +		const Glib::ustring & value() const +		{ +			if (!cacheValid) { +				boost::char_separator<char> sep(" "); +				boost::tokenizer<boost::char_separator<char> > tokens(source.raw(), sep); +				std::list<Variable::VariableImplPtr> vars; +				size_t len = 0; +				BOOST_FOREACH(std::string t, tokens) { +					Variable::VariableImplPtr vip = Variable::create(t); +					len += vip->value().length() + 1; +					vars.push_back(vip); +				} +				cache.reserve(len); +				BOOST_FOREACH(Variable::VariableImplPtr v, vars) { +					if (cache.length()) { +						cache.append(" "); +					} +					cache.append(v->value()); +				} +				cacheValid = true; +			} +			return cache; +		} +}; + +Variable::Variable(const Glib::ustring & s) : +	var(create(s)) +{ +} + +Variable::Variable(xmlpp::Attribute * a) : +	var(create(a->get_value())) +{ +} + +Variable::Variable(xmlpp::Element * e) : +	var(create(e->get_child_text()->get_content())) +{ +} + +Variable::VariableImplPtr +Variable::create(const Glib::ustring & 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)); +		case '/': // uri +			return VariableImplPtr(new VariableUri(s)); +		case '*': // parser +			return VariableImplPtr(new VariableParse(s)); +		case '=': // literal (explicit) +			return VariableImplPtr(new VariableParse(s.substr(1))); +		default: +			return VariableImplPtr(new VariableLiteral(s)); +	} +} + diff --git a/project2/variables.h b/project2/variables.h new file mode 100644 index 0000000..cba303e --- /dev/null +++ b/project2/variables.h @@ -0,0 +1,37 @@ +#ifndef VARIABLES_H +#define VARIABLES_H + +#include <boost/shared_ptr.hpp> +#include <glibmm/ustring.h> +#include <libxml++/nodes/element.h> +#include <libxml++/attribute.h> + +class VariableImpl { +	public: +		virtual const Glib::ustring & value() const = 0; + +	protected: +		VariableImpl(const Glib::ustring & src) : source(src) { } +		const Glib::ustring source; +}; + + +class Variable { +	public: +		typedef boost::shared_ptr<VariableImpl> VariableImplPtr; + +		Variable(xmlpp::Attribute *); +		Variable(xmlpp::Element *); +		Variable(const Glib::ustring & s); + +		operator const Glib::ustring & () const { return var->value(); } +		const Glib::ustring & operator()() const { return var->value(); } + +	private: +		friend class VariableParse; +		static VariableImplPtr create(const Glib::ustring & s); +		VariableImplPtr var; +}; + +#endif + diff --git a/project2/view.cpp b/project2/view.cpp index c36c43d..3a99aa6 100644 --- a/project2/view.cpp +++ b/project2/view.cpp @@ -24,8 +24,16 @@ _View::AddLoaders(Loaders & l, Views & views)  void  _View::executeChildren(xmlpp::Element * record, const ApplicationEngine * ep, const _View * parent) const  { -	BOOST_FOREACH(Views::value_type sq, subViews) { -		sq.second->execute(record, ep, this); +	try { +		PerRowValues::beginRow(this); +		BOOST_FOREACH(Views::value_type sq, subViews) { +			sq.second->execute(record, ep, this); +		} +		PerRowValues::endRow(this); +	} +	catch (...) { +		PerRowValues::endRow(this); +		throw;  	}  }  | 
