diff options
| -rw-r--r-- | project2/common/if.cpp | 71 | ||||
| -rw-r--r-- | project2/common/if.h | 9 | ||||
| -rw-r--r-- | project2/common/rowProcessor.cpp | 2 | ||||
| -rw-r--r-- | project2/common/rowProcessor.h | 3 | ||||
| -rw-r--r-- | project2/common/scripts.h | 3 | ||||
| -rw-r--r-- | project2/common/sourceObject.cpp | 30 | ||||
| -rw-r--r-- | project2/common/sourceObject.h | 15 | ||||
| -rw-r--r-- | project2/common/test.cpp | 5 | ||||
| -rw-r--r-- | project2/common/test.h | 1 | ||||
| -rw-r--r-- | project2/common/tests/compoundTest.cpp | 79 | ||||
| -rw-r--r-- | project2/common/tests/compoundTest.h | 16 | ||||
| -rw-r--r-- | project2/common/tests/isdistinct.cpp | 40 | ||||
| -rw-r--r-- | project2/common/tests/isuniq.cpp | 48 | ||||
| -rw-r--r-- | project2/common/variables-modlookup.cpp | 1 | ||||
| -rw-r--r-- | project2/common/variables.cpp | 73 | ||||
| -rw-r--r-- | project2/common/variables.h | 14 | 
16 files changed, 315 insertions, 95 deletions
diff --git a/project2/common/if.cpp b/project2/common/if.cpp index b9db1db..c7f790e 100644 --- a/project2/common/if.cpp +++ b/project2/common/if.cpp @@ -9,13 +9,6 @@  DECLARE_LOADER("if", If);  StaticMessageException(NoTestsToPerform, "No tests to perform"); -CompoundTest::CompoundTest(ScriptNodePtr s) : -	SourceObject(s), -	Test(s) -{ -	s->script->loader.addLoadTarget(s, Storer::into<ElementLoader>(&tests)); -} -  If::If(ScriptNodePtr e) :  	SourceObject(e),  	IHaveSubTasks(e), @@ -55,67 +48,3 @@ If::execute() const  	}  } - -class All : public CompoundTest { -	public: -		All(ScriptNodePtr s) : -			SourceObject(s), -			CompoundTest(s) { -		} -		bool passes() const { -			if (tests.empty()) { -				throw NoTestsToPerform(); -			} -			return (std::find_if(tests.begin(), tests.end(), !boost::bind(&Test::passes, _1)) == tests.end()); -		} -}; -DECLARE_LOADER("all", All); - -class Any : public CompoundTest { -	public: -		Any(ScriptNodePtr s) : -			SourceObject(s), -			CompoundTest(s) { -		} -		bool passes() const { -			if (tests.empty()) { -				throw NoTestsToPerform(); -			} -			return (std::find_if(tests.begin(), tests.end(), boost::bind(&Test::passes, _1)) != tests.end()); -		} -}; -DECLARE_LOADER("any", Any); - -class None : public CompoundTest { -	public: -		None(ScriptNodePtr s) : -			SourceObject(s), -			CompoundTest(s) { -		} -		bool passes() const { -			if (tests.empty()) { -				throw NoTestsToPerform(); -			} -			return (std::find_if(tests.begin(), tests.end(), boost::bind(&Test::passes, _1)) == tests.end()); -		} -}; -DECLARE_LOADER("none", None); - -class Not : public Test { -	public: -		Not(ScriptNodePtr s) : -			SourceObject(s), -			Test(s) -		{ -			s->script->loader.addLoadTarget(s, Storer::into<ElementLoader>(&test)); -		} -		bool passes() const { -			if (!test) { -				throw NoTestsToPerform(); -			} -			return !test->passes(); -		} -	private: -		TestPtr test; -}; -DECLARE_LOADER("not", Not); diff --git a/project2/common/if.h b/project2/common/if.h index bcf83cd..2496dc4 100644 --- a/project2/common/if.h +++ b/project2/common/if.h @@ -5,15 +5,6 @@  #include "view.h"  #include "test.h" -class CompoundTest : public Test { -	public: -		CompoundTest(ScriptNodePtr); - -	protected: -		typedef ANONORDEREDSTORAGEOF(Test) Tests; -		Tests tests; -}; -  /// Project2 component to conditionally execute its children  class If : public IHaveSubTasks, public View {  	public: diff --git a/project2/common/rowProcessor.cpp b/project2/common/rowProcessor.cpp index 541ff11..f83dfa7 100644 --- a/project2/common/rowProcessor.cpp +++ b/project2/common/rowProcessor.cpp @@ -7,6 +7,7 @@  #include <boost/algorithm/string/predicate.hpp>  RowProcessor::RowProcessor(ScriptNodePtr p) : +	SourceObject(p),  	IHaveParameters(p),  	recordSource(p->value("source").as<std::string>()),  	filter(p->value("filter", "").as<Glib::ustring>()), @@ -42,6 +43,7 @@ RowProcessor::execute() const  		}  	}  	Logger()->messagebf(LOG_DEBUG, "Executing from source '%s'", source->name); +	ScopeObject onComplete(boost::bind(&SourceObject::send, this, Complete));  	if (IRSE) {  		try {  			source->execute(filter, this); diff --git a/project2/common/rowProcessor.h b/project2/common/rowProcessor.h index cbbf6c3..a7e8544 100644 --- a/project2/common/rowProcessor.h +++ b/project2/common/rowProcessor.h @@ -12,8 +12,9 @@  class Presenter;  /// Base class for Project2 components that work with row sets -class RowProcessor : public IHaveParameters { +class RowProcessor : public IHaveParameters, public virtual SourceObject {  	public: +		enum EventIDs { Complete };  		RowProcessor(ScriptNodePtr);  		void loadComplete(const CommonObjects *); diff --git a/project2/common/scripts.h b/project2/common/scripts.h index 0f1a1a6..ce2cf0e 100644 --- a/project2/common/scripts.h +++ b/project2/common/scripts.h @@ -55,6 +55,9 @@ class ScriptReader : public virtual IntrusivePtrBase {  		virtual bool isCurrent() const = 0;  		virtual time_t modifiedTime() const = 0;  		mutable LoaderBase loader; + +		friend class SourceObject; +		mutable std::map<std::string, SourceObject *> namedComponents;  };  /// Base class to implement script reader modules diff --git a/project2/common/sourceObject.cpp b/project2/common/sourceObject.cpp index ef909b9..6f5bcc5 100644 --- a/project2/common/sourceObject.cpp +++ b/project2/common/sourceObject.cpp @@ -1,18 +1,24 @@  #include <pch.hpp>  #include "sourceObject.h" +#include "exceptions.h" +#include "safeMapFind.h"  unsigned int SourceObject::loadOrder = 1; +SimpleMessageException(ComponentNotFound);  SourceObject::SourceObject(ScriptNodePtr p) :  	name(p ? p->value("name", "anon").as<std::string>() : "anon"), -	order(loadOrder++) +	order(loadOrder++), +	script(p->script.get())  {  	LoaderBase::loadedObjects.insert(this); +	script->namedComponents[name] = this;  }  SourceObject::SourceObject(const std::string & n) :  	name(n), -	order(loadOrder++) +	order(loadOrder++), +	script(NULL)  {  	LoaderBase::loadedObjects.insert(this);  } @@ -27,3 +33,23 @@ SourceObject::loadComplete(const CommonObjects *)  {  } +void +SourceObject::send(int eventID) const +{ +	for (Events::const_iterator i = events.lower_bound(eventID); i != events.upper_bound(eventID); i++) { +		i->second(); +	} +} + +void +SourceObject::registerFor(int eventID, const Event & event) const +{ +	events.insert(Events::value_type(eventID, event)); +} + +SourceObject * +SourceObject::findComponent(const std::string & name) const +{ +	return safeMapLookup<ComponentNotFound>(script->namedComponents, name); +} + diff --git a/project2/common/sourceObject.h b/project2/common/sourceObject.h index f8963ea..8529100 100644 --- a/project2/common/sourceObject.h +++ b/project2/common/sourceObject.h @@ -3,6 +3,7 @@  #include <boost/intrusive_ptr.hpp>  #include <string> +#include <map>  #include "intrusivePtrBase.h"  #include "scriptLoader.h"  #include "scripts_fwd.h" @@ -15,16 +16,30 @@ class CommonObjects;  /// Base class for all Project2 components that can be placed in a Project2 script  class SourceObject : public virtual IntrusivePtrBase {  	public: +		typedef int EventID; +		typedef boost::function<void()> Event; +		typedef std::multimap<EventID, Event> Events; +  		SourceObject(ScriptNodePtr p);  		SourceObject(const std::string & name);  		virtual ~SourceObject() = 0;  		virtual void loadComplete(const CommonObjects *); +		SourceObject * findComponent(const std::string & name) const; + +		void registerFor(EventID eventID, const Event & event) const; +		void send(EventID eventID) const; +  		const std::string name;  		const unsigned int order; + +  	private:  		static unsigned int loadOrder; + +		mutable Events events; +		const ScriptReader * const script;  };  #endif diff --git a/project2/common/test.cpp b/project2/common/test.cpp index f4066af..427848a 100644 --- a/project2/common/test.cpp +++ b/project2/common/test.cpp @@ -5,3 +5,8 @@ Test::Test(ScriptNodePtr s) :  {  } +void +Test::reset() const +{ +} + diff --git a/project2/common/test.h b/project2/common/test.h index aa2709c..4f87c10 100644 --- a/project2/common/test.h +++ b/project2/common/test.h @@ -8,6 +8,7 @@ class Test : public virtual SourceObject {  	public:  		Test(ScriptNodePtr);  		virtual bool passes() const = 0; +		virtual void reset() const;  };  typedef boost::intrusive_ptr<const Test> TestPtr; diff --git a/project2/common/tests/compoundTest.cpp b/project2/common/tests/compoundTest.cpp new file mode 100644 index 0000000..c3babf7 --- /dev/null +++ b/project2/common/tests/compoundTest.cpp @@ -0,0 +1,79 @@ +#include <pch.hpp> +#include "compoundTest.h" +#include "../scriptLoader.h" +#include <boost/foreach.hpp> +#include <boost/bind.hpp> +#include <algorithm> + +StaticMessageException(NoTestsToPerform, "No tests to perform"); + +CompoundTest::CompoundTest(ScriptNodePtr s) : +	SourceObject(s), +	Test(s) +{ +	s->script->loader.addLoadTarget(s, Storer::into<ElementLoader>(&tests)); +} + +class All : public CompoundTest { +	public: +		All(ScriptNodePtr s) : +			SourceObject(s), +			CompoundTest(s) { +		} +		bool passes() const { +			if (tests.empty()) { +				throw NoTestsToPerform(); +			} +			return (std::find_if(tests.begin(), tests.end(), !boost::bind(&Test::passes, _1)) == tests.end()); +		} +}; +DECLARE_LOADER("all", All); + +class Any : public CompoundTest { +	public: +		Any(ScriptNodePtr s) : +			SourceObject(s), +			CompoundTest(s) { +		} +		bool passes() const { +			if (tests.empty()) { +				throw NoTestsToPerform(); +			} +			return (std::find_if(tests.begin(), tests.end(), boost::bind(&Test::passes, _1)) != tests.end()); +		} +}; +DECLARE_LOADER("any", Any); + +class None : public CompoundTest { +	public: +		None(ScriptNodePtr s) : +			SourceObject(s), +			CompoundTest(s) { +		} +		bool passes() const { +			if (tests.empty()) { +				throw NoTestsToPerform(); +			} +			return (std::find_if(tests.begin(), tests.end(), boost::bind(&Test::passes, _1)) == tests.end()); +		} +}; +DECLARE_LOADER("none", None); + +class Not : public Test { +	public: +		Not(ScriptNodePtr s) : +			SourceObject(s), +			Test(s) +		{ +			s->script->loader.addLoadTarget(s, Storer::into<ElementLoader>(&test)); +		} +		bool passes() const { +			if (!test) { +				throw NoTestsToPerform(); +			} +			return !test->passes(); +		} +	private: +		TestPtr test; +}; +DECLARE_LOADER("not", Not); diff --git a/project2/common/tests/compoundTest.h b/project2/common/tests/compoundTest.h new file mode 100644 index 0000000..38aadea --- /dev/null +++ b/project2/common/tests/compoundTest.h @@ -0,0 +1,16 @@ +#ifndef IF_H +#define IF_H + +#include "../test.h" + +class CompoundTest : public Test { +	public: +		CompoundTest(ScriptNodePtr); + +	protected: +		typedef ANONORDEREDSTORAGEOF(Test) Tests; +		Tests tests; +}; + +#endif + diff --git a/project2/common/tests/isdistinct.cpp b/project2/common/tests/isdistinct.cpp new file mode 100644 index 0000000..b754d2d --- /dev/null +++ b/project2/common/tests/isdistinct.cpp @@ -0,0 +1,40 @@ +#include <pch.hpp> +#include "../test.h" +#include "../scriptLoader.h" +#include "../iHaveParameters.h" +#include "../rowProcessor.h" + +class IsDistinct : public Test, IHaveParameters { +	public: +		IsDistinct(ScriptNodePtr s) : +			SourceObject(s), +			Test(s), +			IHaveParameters(s), +			scope(s, "scope") +		{ +		} +		 +		void loadComplete(const CommonObjects *) +		{ +			findComponent(scope())->registerFor(RowProcessor::Complete, boost::bind(&IsDistinct::reset, this)); +		} + +		bool passes() const { +			Vars row; +			BOOST_FOREACH(const Parameters::value_type & p, parameters) { +				row.push_back(p.second()); +			} +			return previous.insert(row).second; +		} +		 +		void reset() const { +			previous.clear(); +		} + +	private: +		Variable scope; +		typedef std::vector<VariableType> Vars; +		typedef std::set<Vars> Rows; +		mutable Rows previous; +}; +DECLARE_LOADER("isdistinct", IsDistinct); diff --git a/project2/common/tests/isuniq.cpp b/project2/common/tests/isuniq.cpp new file mode 100644 index 0000000..6966985 --- /dev/null +++ b/project2/common/tests/isuniq.cpp @@ -0,0 +1,48 @@ +#include <pch.hpp> +#include "../test.h" +#include "../scriptLoader.h" +#include "../iHaveParameters.h" +#include "../rowProcessor.h" + +class IsUniq : public Test, IHaveParameters { +	public: +		IsUniq(ScriptNodePtr s) : +			SourceObject(s), +			Test(s), +			IHaveParameters(s), +			scope(s, "scope") +		{ +		} + +		void loadComplete(const CommonObjects *) +		{ +			findComponent(scope())->registerFor(RowProcessor::Complete, boost::bind(&IsUniq::reset, this)); +		} + +		bool passes() const { +			if (previous.size() > 0) { +				Vars row; +				BOOST_FOREACH(const Parameters::value_type & p, parameters) { +					row.push_back(p.second()); +				} +				std::swap(row, previous); +				return row != previous; +			} +			else { +				BOOST_FOREACH(const Parameters::value_type & p, parameters) { +					previous.push_back(p.second()); +				} +				return true; +			} +		} +		 +		void reset() const { +			previous.clear(); +		} + +	private: +		Variable scope; +		typedef std::vector<VariableType> Vars; +		mutable Vars previous; +}; +DECLARE_LOADER("isuniq", IsUniq); diff --git a/project2/common/variables-modlookup.cpp b/project2/common/variables-modlookup.cpp index 64ff93d..67d2924 100644 --- a/project2/common/variables-modlookup.cpp +++ b/project2/common/variables-modlookup.cpp @@ -31,6 +31,7 @@ class VariableLookup : public VariableImplDyn, public RowProcessor {  				}  		};  		VariableLookup(ScriptNodePtr e) : +			SourceObject(e),  			VariableImplDyn(e),  			RowProcessor(e),  			name(e->value("name").as<Glib::ustring>()) diff --git a/project2/common/variables.cpp b/project2/common/variables.cpp index 8515e44..4b42aa3 100644 --- a/project2/common/variables.cpp +++ b/project2/common/variables.cpp @@ -18,12 +18,6 @@  SimpleMessageException(UnknownVariableType); -bool -Null::operator<(const Null &) const -{ -	return false; -} -  Boolean::Boolean(bool v) : value(v)  {  } @@ -159,13 +153,13 @@ VariableType::VariableType(const VariableType & vt) :  {  } -template <class S> +template <class S, typename Op>  class compi : public boost::static_visitor<bool> {  	public:  		compi(const S & s) : _s(s) { }  		bool operator()(const S & t) const  		{ -			return t < _s; +			return Op()(t, _s);  		}  		template <class T>  		bool operator()(const T &) const @@ -176,13 +170,15 @@ class compi : public boost::static_visitor<bool> {  	private:  		const S & _s;  }; + +template <template <class T> class Op>  class comp : public boost::static_visitor<bool> {  	public:  		comp(const VariableType & a) : _a(a) { }  		template <class T>  		bool operator()(const T & t) const  		{ -			return boost::apply_visitor(compi<T>(t), _a); +			return boost::apply_visitor(compi<T, Op<T>>(t), _a);  		}  	private:  		const VariableType & _a; @@ -195,7 +191,64 @@ VariableType::operator<(const VariableType & b) const  		return true;  	}  	if (this->which() == b.which()) { -		return boost::apply_visitor(comp(*this), b); +		return boost::apply_visitor(comp<std::less>(*this), b); +	} +	return false; +} + +bool +VariableType::operator==(const VariableType & b) const +{ +	if (this->which() == b.which()) { +		return boost::apply_visitor(comp<std::equal_to>(*this), b); +	} +	return false; +} + +bool +VariableType::operator<=(const VariableType & b) const +{ +	if (this->which() < b.which()) { +		return true; +	} +	if (this->which() == b.which()) { +		return boost::apply_visitor(comp<std::less_equal>(*this), b); +	} +	return false; +} + +bool +VariableType::operator>(const VariableType & b) const +{ +	if (this->which() > b.which()) { +		return true; +	} +	if (this->which() == b.which()) { +		return boost::apply_visitor(comp<std::greater>(*this), b); +	} +	return false; +} + +bool +VariableType::operator>=(const VariableType & b) const +{ +	if (this->which() > b.which()) { +		return true; +	} +	if (this->which() == b.which()) { +		return boost::apply_visitor(comp<std::greater_equal>(*this), b); +	} +	return false; +} + +bool +VariableType::operator!=(const VariableType & b) const +{ +	if (this->which() != b.which()) { +		return true; +	} +	if (this->which() == b.which()) { +		return boost::apply_visitor(comp<std::not_equal_to>(*this), b);  	}  	return false;  } diff --git a/project2/common/variables.h b/project2/common/variables.h index 932da90..941d754 100644 --- a/project2/common/variables.h +++ b/project2/common/variables.h @@ -26,7 +26,12 @@ enum VT_typeID {  class Null {  	public: -		bool operator<(const Null &) const; +		bool operator<(const Null &) const { return false; } +		bool operator<=(const Null &) const { return false; } +		bool operator>(const Null &) const { return false; } +		bool operator>=(const Null &) const { return false; } +		bool operator!=(const Null &) const { return false; } +		bool operator==(const Null &) const { return true; }  };  class Boolean { @@ -78,6 +83,11 @@ class VariableType : public _VT {  		static VT_typeID getTypeFromName(const std::string & src);  		bool operator<(const VariableType &) const; +		bool operator<=(const VariableType &) const; +		bool operator>(const VariableType &) const; +		bool operator>=(const VariableType &) const; +		bool operator==(const VariableType &) const; +		bool operator!=(const VariableType &) const;  		operator const Glib::ustring &() const;  		operator const std::string &() const; @@ -97,7 +107,7 @@ class VariableType : public _VT {  };  /// Base class for Project2 variable accessors -class VariableImpl : public IntrusivePtrBase { +class VariableImpl : public virtual IntrusivePtrBase {  	public:  		virtual VariableType value() const = 0;  | 
