summaryrefslogtreecommitdiff
path: root/project2/basics
diff options
context:
space:
mode:
Diffstat (limited to 'project2/basics')
-rw-r--r--project2/basics/Jamfile.jam21
-rw-r--r--project2/basics/aggregates/count.cpp28
-rw-r--r--project2/basics/aggregates/countDistinct.cpp26
-rw-r--r--project2/basics/aggregates/distinct.cpp28
-rw-r--r--project2/basics/aggregates/max.cpp27
-rw-r--r--project2/basics/aggregates/min.cpp32
-rw-r--r--project2/basics/functions/dates.cpp90
-rw-r--r--project2/basics/functions/strings.cpp28
-rw-r--r--project2/basics/pch.hpp28
-rw-r--r--project2/basics/tests/compoundTest.cpp79
-rw-r--r--project2/basics/tests/compoundTest.h16
-rw-r--r--project2/basics/tests/equals.cpp24
-rw-r--r--project2/basics/tests/isdistinct.cpp40
-rw-r--r--project2/basics/tests/isuniq.cpp48
-rw-r--r--project2/basics/tests/validDateCheck.cpp66
15 files changed, 581 insertions, 0 deletions
diff --git a/project2/basics/Jamfile.jam b/project2/basics/Jamfile.jam
new file mode 100644
index 0000000..66ec12c
--- /dev/null
+++ b/project2/basics/Jamfile.jam
@@ -0,0 +1,21 @@
+alias glibmm : : : :
+ <cflags>"`pkg-config --cflags glibmm-2.4`"
+ <linkflags>"`pkg-config --libs glibmm-2.4`"
+ ;
+lib boost_filesystem : : <name>boost_filesystem ;
+
+cpp-pch pch : pch.hpp :
+ <include>../../libmisc
+ <library>glibmm
+ <library>../common//p2common
+ ;
+
+lib p2basics :
+ [ glob-tree *.cpp ]
+ :
+ <include>../../libmisc
+ <library>glibmm
+ <library>boost_filesystem
+ <library>../common//p2common
+ ;
+
diff --git a/project2/basics/aggregates/count.cpp b/project2/basics/aggregates/count.cpp
new file mode 100644
index 0000000..fb3b899
--- /dev/null
+++ b/project2/basics/aggregates/count.cpp
@@ -0,0 +1,28 @@
+#include <aggregate.h>
+
+class Count : public ValueAggregate {
+ public:
+ Count(ScriptNodePtr s) :
+ ValueAggregate(s),
+ c(0)
+ {
+ }
+ void reset() const
+ {
+ c = 0;
+ }
+ void pushValue(const VariableType &) const
+ {
+ c += 1;
+ }
+ VariableType resultValue() const
+ {
+ return c;
+ }
+ private:
+ mutable int c;
+};
+
+DECLARE_LOADER("count", Count);
+
+
diff --git a/project2/basics/aggregates/countDistinct.cpp b/project2/basics/aggregates/countDistinct.cpp
new file mode 100644
index 0000000..b471911
--- /dev/null
+++ b/project2/basics/aggregates/countDistinct.cpp
@@ -0,0 +1,26 @@
+#include <aggregate.h>
+
+class CountDistinct : public ValueAggregate {
+ public:
+ CountDistinct(ScriptNodePtr s) :
+ ValueAggregate(s)
+ {
+ }
+ void reset() const
+ {
+ result.clear();
+ }
+ void pushValue(const VariableType & v) const
+ {
+ result.insert(v);
+ }
+ VariableType resultValue() const
+ {
+ return result.size();
+ }
+ private:
+ mutable std::set<VariableType> result;
+};
+
+DECLARE_LOADER("countdistinct", CountDistinct);
+
diff --git a/project2/basics/aggregates/distinct.cpp b/project2/basics/aggregates/distinct.cpp
new file mode 100644
index 0000000..ebac934
--- /dev/null
+++ b/project2/basics/aggregates/distinct.cpp
@@ -0,0 +1,28 @@
+#include <aggregate.h>
+#include <boost/foreach.hpp>
+
+class Distinct : public SetAggregate {
+ public:
+ Distinct(ScriptNodePtr s) :
+ SetAggregate(s)
+ {
+ }
+ void reset() const
+ {
+ result.clear();
+ }
+ void pushValue(const VariableType & v) const
+ {
+ result.insert(v);
+ }
+ void onResultValues(const SetAggregate::UseAgg & u) const
+ {
+ BOOST_FOREACH(const VariableType & v, result) {
+ u(v);
+ }
+ }
+ private:
+ mutable std::set<VariableType> result;
+};
+
+DECLARE_LOADER("distinct", Distinct);
diff --git a/project2/basics/aggregates/max.cpp b/project2/basics/aggregates/max.cpp
new file mode 100644
index 0000000..ef904ed
--- /dev/null
+++ b/project2/basics/aggregates/max.cpp
@@ -0,0 +1,27 @@
+#include <aggregate.h>
+
+class Max : public ValueAggregate {
+ public:
+ Max(ScriptNodePtr s) : ValueAggregate(s) { }
+
+ void reset() const
+ {
+ result = VariableType();
+ }
+ void pushValue(const VariableType & v) const
+ {
+ if (result < v) {
+ result = v;
+ }
+ }
+ VariableType resultValue() const
+ {
+ return result;
+ }
+ private:
+ mutable VariableType result;
+};
+
+DECLARE_LOADER("max", Max);
+
+
diff --git a/project2/basics/aggregates/min.cpp b/project2/basics/aggregates/min.cpp
new file mode 100644
index 0000000..ee0bf3d
--- /dev/null
+++ b/project2/basics/aggregates/min.cpp
@@ -0,0 +1,32 @@
+#include <aggregate.h>
+
+class Min : public ValueAggregate {
+ public:
+ Min(ScriptNodePtr s) :
+ ValueAggregate(s),
+ first(true)
+ {
+ }
+ void reset() const
+ {
+ result = VariableType();
+ first = true;
+ }
+ void pushValue(const VariableType & v) const
+ {
+ if (first || v < result) {
+ result = v;
+ }
+ first = false;
+ }
+ VariableType resultValue() const
+ {
+ return result;
+ }
+ private:
+ mutable VariableType result;
+ mutable bool first;
+};
+
+DECLARE_LOADER("min", Min);
+
diff --git a/project2/basics/functions/dates.cpp b/project2/basics/functions/dates.cpp
new file mode 100644
index 0000000..f2dcb20
--- /dev/null
+++ b/project2/basics/functions/dates.cpp
@@ -0,0 +1,90 @@
+#include <pch.hpp>
+#include <variables.h>
+#include <scriptLoader.h>
+#include <scriptStorage.h>
+#include <logger.h>
+#include <locale>
+#include <iostream>
+#include <boost/date_time.hpp>
+
+SimpleMessage2Exception(DateParseError);
+/// Variable implementation to access platform configuration values
+class ParseDate : public VariableImpl {
+ public:
+ ParseDate(ScriptNodePtr e) :
+ string(e, "string"),
+ format(e, "format")
+ {
+ }
+ VariableType value() const
+ {
+ const char * s = string();
+ const char * f = format();
+ struct tm tm;
+ memset(&tm, 0, sizeof(struct tm));
+ mktime(&tm);
+ const char * e = strptime(s, f, &tm);
+ if (!e || *e) {
+ Logger()->messagef(LOG_ERR, "%s: check failed (parse) for '%s' against '%s' (remaining chars='%s')",
+ __PRETTY_FUNCTION__, s, f, e);
+ throw DateParseError(string(), format());
+ }
+ return boost::posix_time::ptime(boost::posix_time::ptime_from_tm(tm));
+ }
+ private:
+ Variable string;
+ Variable format;
+};
+DECLARE_COMPONENT_LOADER("parsedate", ParseDate, VariableLoader);
+
+class FormatDate : public VariableImpl {
+ public:
+ FormatDate(ScriptNodePtr e) :
+ date(e, "date"),
+ format(e, "format")
+ {
+ }
+ VariableType value() const
+ {
+ std::stringstream ss;
+ boost::date_time::time_facet<boost::posix_time::ptime, char> * ft = new boost::date_time::time_facet<boost::posix_time::ptime, char>();
+ ss.imbue(std::locale(ss.getloc(), ft));
+ ft->format(format());
+ ss << boost::get<boost::posix_time::ptime>(date());
+ return ss.str();
+ }
+ private:
+ Variable date;
+ Variable format;
+};
+DECLARE_COMPONENT_LOADER("formatdate", FormatDate, VariableLoader);
+
+class AdjustDate : public VariableImpl {
+ public:
+ AdjustDate(ScriptNodePtr e) :
+ date(e, "date"),
+ offset(e, "offset")
+ {
+ }
+ VariableType value() const
+ {
+ return boost::get<boost::posix_time::ptime>(date()) + boost::posix_time::duration_from_string(offset());
+ }
+ private:
+ Variable date;
+ Variable offset;
+};
+DECLARE_COMPONENT_LOADER("adjustdate", AdjustDate, VariableLoader);
+
+class CurrentDate : public VariableImpl {
+ public:
+ CurrentDate(ScriptNodePtr)
+ {
+ }
+ VariableType value() const
+ {
+ return boost::posix_time::microsec_clock::universal_time();
+ }
+};
+DECLARE_COMPONENT_LOADER("currentdate", CurrentDate, VariableLoader);
+
diff --git a/project2/basics/functions/strings.cpp b/project2/basics/functions/strings.cpp
new file mode 100644
index 0000000..d4ba7b7
--- /dev/null
+++ b/project2/basics/functions/strings.cpp
@@ -0,0 +1,28 @@
+#include <pch.hpp>
+#include <variables.h>
+#include <scriptLoader.h>
+#include <scriptStorage.h>
+
+/// Variable implementation to access platform configuration values
+class Trim : public VariableImpl {
+ public:
+ Trim(ScriptNodePtr e) :
+ string(e, "string")
+ {
+ }
+ VariableType value() const
+ {
+ Glib::ustring str = string();
+ Glib::ustring::const_iterator b = str.begin();
+ while (Glib::Unicode::isspace(*b)) ++b;
+ Glib::ustring::const_iterator e = str.end();
+ while (Glib::Unicode::isspace(*--e)) ;
+ ++e;
+ return Glib::ustring(b, e);
+ }
+ private:
+ Variable string;
+};
+DECLARE_COMPONENT_LOADER("trim", Trim, VariableLoader);
+
+
diff --git a/project2/basics/pch.hpp b/project2/basics/pch.hpp
new file mode 100644
index 0000000..d52b275
--- /dev/null
+++ b/project2/basics/pch.hpp
@@ -0,0 +1,28 @@
+#ifdef BOOST_BUILD_PCH_ENABLED
+#ifndef COMMON_PCH
+#define COMMON_PCH
+
+#include <aggregate.h>
+#include <algorithm>
+#include <appEngine.h>
+#include <boost/algorithm/string/predicate.hpp>
+#include <boost/bind.hpp>
+#include <boost/date_time.hpp>
+#include <boost/filesystem/operations.hpp>
+#include <boost/foreach.hpp>
+#include <commonObjects.h>
+#include <iHaveParameters.h>
+#include <iostream>
+#include <list>
+#include <logger.h>
+#include <rowProcessor.h>
+#include <rowSet.h>
+#include <safeMapFind.h>
+#include <scriptLoader.h>
+#include <scripts.h>
+#include <scriptStorage.h>
+#include <test.h>
+#include <variables.h>
+
+#endif
+#endif
diff --git a/project2/basics/tests/compoundTest.cpp b/project2/basics/tests/compoundTest.cpp
new file mode 100644
index 0000000..b361db5
--- /dev/null
+++ b/project2/basics/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/basics/tests/compoundTest.h b/project2/basics/tests/compoundTest.h
new file mode 100644
index 0000000..f65e954
--- /dev/null
+++ b/project2/basics/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/basics/tests/equals.cpp b/project2/basics/tests/equals.cpp
new file mode 100644
index 0000000..ba8c695
--- /dev/null
+++ b/project2/basics/tests/equals.cpp
@@ -0,0 +1,24 @@
+#include <pch.hpp>
+#include <test.h>
+#include <scriptLoader.h>
+#include <rowProcessor.h>
+
+class Equals : public Test {
+ public:
+ Equals(ScriptNodePtr s) :
+ SourceObject(s),
+ Test(s),
+ a(s, "a"),
+ b(s, "b")
+ {
+ }
+
+ bool passes() const {
+ return (a() == b());
+ }
+
+ private:
+ Variable a, b;
+};
+DECLARE_LOADER("equals", Equals);
+
diff --git a/project2/basics/tests/isdistinct.cpp b/project2/basics/tests/isdistinct.cpp
new file mode 100644
index 0000000..06d887e
--- /dev/null
+++ b/project2/basics/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/basics/tests/isuniq.cpp b/project2/basics/tests/isuniq.cpp
new file mode 100644
index 0000000..548be14
--- /dev/null
+++ b/project2/basics/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/basics/tests/validDateCheck.cpp b/project2/basics/tests/validDateCheck.cpp
new file mode 100644
index 0000000..8dffd9d
--- /dev/null
+++ b/project2/basics/tests/validDateCheck.cpp
@@ -0,0 +1,66 @@
+#include <pch.hpp>
+#include <logger.h>
+#include <scriptLoader.h>
+#include <commonObjects.h>
+#include <test.h>
+#include <variables.h>
+#include <scripts.h>
+
+class ValidDateTest : public Test {
+ public:
+ ValidDateTest(ScriptNodePtr p) :
+ SourceObject(p),
+ Test(p),
+ applyTo(p, "apply-to"),
+ format(p, "format"),
+ warnLev(p->value("warn", true).as<bool>() ? LOG_WARNING : LOG_INFO)
+ {
+ }
+
+ ~ValidDateTest()
+ {
+ }
+
+ bool
+ passes() const
+ {
+ struct tm tm, ftm;
+ memset(&tm, 0, sizeof(struct tm));
+ mktime(&tm);
+ const char * at = applyTo();
+ const char * f = format();
+ const char * s = strptime(at, f, &tm);
+ if (!s || *s) {
+ Logger()->messagef(warnLev, "%s: check failed (parse) for '%s' against '%s'",
+ __PRETTY_FUNCTION__, at, f);
+ return false;
+ }
+ ftm = tm;
+ if (mktime(&ftm) == -1) {
+ Logger()->messagef(warnLev, "%s: check failed (normalise) for '%s' against '%s'",
+ __PRETTY_FUNCTION__, at, f);
+ return false;
+ }
+ if (tm.tm_year != ftm.tm_year ||
+ tm.tm_mon != ftm.tm_mon ||
+ tm.tm_mday != ftm.tm_mday ||
+ tm.tm_hour != (ftm.tm_hour - ftm.tm_isdst) ||
+ tm.tm_min != ftm.tm_min ||
+ tm.tm_sec != ftm.tm_sec) {
+ Logger()->messagef(LOG_INFO, "tm: %d %d %d %d %d %d",
+ tm.tm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
+ Logger()->messagef(LOG_INFO, "ftm: %d %d %d %d %d %d",
+ ftm.tm_year, ftm.tm_mon, ftm.tm_mday, ftm.tm_hour, ftm.tm_min, ftm.tm_sec);
+ Logger()->messagef(warnLev, "%s: check failed (verify) for '%s' against '%s'",
+ __PRETTY_FUNCTION__, at, f);
+ return false;
+ }
+ return true;
+ }
+ Variable applyTo;
+ Variable format;
+ int warnLev;
+};
+
+DECLARE_LOADER("validdatetest", ValidDateTest);
+