diff options
Diffstat (limited to 'project2/basics')
-rw-r--r-- | project2/basics/Jamfile.jam | 21 | ||||
-rw-r--r-- | project2/basics/aggregates/count.cpp | 28 | ||||
-rw-r--r-- | project2/basics/aggregates/countDistinct.cpp | 26 | ||||
-rw-r--r-- | project2/basics/aggregates/distinct.cpp | 28 | ||||
-rw-r--r-- | project2/basics/aggregates/max.cpp | 27 | ||||
-rw-r--r-- | project2/basics/aggregates/min.cpp | 32 | ||||
-rw-r--r-- | project2/basics/functions/dates.cpp | 90 | ||||
-rw-r--r-- | project2/basics/functions/strings.cpp | 28 | ||||
-rw-r--r-- | project2/basics/pch.hpp | 28 | ||||
-rw-r--r-- | project2/basics/tests/compoundTest.cpp | 79 | ||||
-rw-r--r-- | project2/basics/tests/compoundTest.h | 16 | ||||
-rw-r--r-- | project2/basics/tests/equals.cpp | 24 | ||||
-rw-r--r-- | project2/basics/tests/isdistinct.cpp | 40 | ||||
-rw-r--r-- | project2/basics/tests/isuniq.cpp | 48 | ||||
-rw-r--r-- | project2/basics/tests/validDateCheck.cpp | 66 |
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); + |