diff --git a/src/lib/time/control.hpp b/src/lib/time/control.hpp index 1ec66acea..2a813aff6 100644 --- a/src/lib/time/control.hpp +++ b/src/lib/time/control.hpp @@ -59,6 +59,7 @@ #define LIB_TIME_CONTROL_H #include "lib/error.hpp" +#include "lib/meta/util.hpp" #include "lib/time/mutation.hpp" #include "lib/time/timevalue.hpp" //#include "lib/symbol.hpp" @@ -66,6 +67,7 @@ //#include //#include //#include +#include #include #include //#include @@ -83,6 +85,9 @@ namespace time { namespace mutation { + using boost::enable_if; + using boost::disable_if; + using lumiera::typelist::is_sameType; using std::tr1::placeholders::_1; using std::tr1::function; using std::tr1::bind; @@ -110,6 +115,9 @@ namespace time { static TI imposeOffset (TimeValue& target, Offset const&); static TI imposeNudge (TimeValue& target, int); + static TI changeDuration (Duration& target, TI const&); +// static TI nudgeDuration (Duration& target, int); + template struct MutationPolicy; @@ -157,10 +165,88 @@ namespace time { return TI (Mutation::imposeChange (target, TimeVar(target)+Time(FSecs(off_by_steps)))); } + // special cases... + template + TI + Mutator::changeDuration (Duration&, TI const&) + { + return TI (Time::ZERO); + } + template<> + Duration + Mutator::changeDuration (Duration& target, Duration const& changedDur) + { + return Duration (Mutation::imposeChange (target,changedDur)); + } + template<> + TimeSpan + Mutator::changeDuration (Duration& target, TimeSpan const& timeSpan_to_impose) + { + return TimeSpan (timeSpan_to_impose.start() + ,Duration(Mutation::imposeChange (target,timeSpan_to_impose.duration())) + ); + } + + template<> + TimeSpan + Mutator::imposeValueChange (TimeValue& target, TimeSpan const& newVal) + { + Mutation::imposeChange (target,newVal); + return newVal; + } + template<> + TimeSpan + Mutator::imposeOffset (TimeValue& target, Offset const& off) + { + return TimeSpan (Mutation::imposeChange (target, TimeVar(target)+off), Duration::ZERO); + } + template<> + TimeSpan + Mutator::imposeNudge (TimeValue& target, int off_by_steps) + { + return TimeSpan (Mutation::imposeChange (target, TimeVar(target)+Time(FSecs(off_by_steps))), Duration::ZERO); + } + + +#ifdef LIB_TIME_TIMEQUQNT_H + template<> + QuTime + Mutator::changeDuration (Duration&, QuTime const& irrelevantChange) + { + return QuTime (Time::ZERO, PQuant(irrelevantChange)); + } + template<> + QuTime + Mutator::imposeValueChange (TimeValue& target, QuTime const& grid_aligned_Value_to_set) + { + PQuant quantiser (grid_aligned_Value_to_set); + TimeValue appliedChange = quantiser->materialise(grid_aligned_Value_to_set); + Mutation::imposeChange (target, appliedChange); + return QuTime (target, quantiser); + } + template<> + QuTime + Mutator::imposeOffset (TimeValue&, Offset const&) + { + throw error::Logic ("can't deliver result of the change as grid-aligned time, " + "because it's not evident which concrete grid to use" + ,LUMIERA_ERROR_UNKNOWN_GRID); //////////////////TODO: we could pick up a "default grid" from session? + } + template<> + QuTime + Mutator::imposeNudge (TimeValue&, int) + { + throw error::Logic ("can't deliver result of the change as grid-aligned time, " + "because it's not evident which concrete grid to use" + ,LUMIERA_ERROR_UNKNOWN_GRID); + } +#endif //(End)quantisation special case + + template template - struct Mutator::MutationPolicy + struct Mutator::MutationPolicy, TI>::type, TAR> { static function buildChangeHandler (TAR& target) @@ -192,6 +278,46 @@ namespace time { }; + //special cases for changing Durations.... + + template + template + struct Mutator::MutationPolicy, TI>::type, TAR> + { + static function + buildChangeHandler (Duration& target) + { + return bind (Mutator::changeDuration, ref(target), _1 ); + } + }; + + // +// template +// template +// struct Mutator::MutationPolicy +// { +// static function +// buildChangeHandler (Duration& target) +// { +// return bind (Mutator::changeDuration, ref(target), _1 ); +// } +// }; + +// template +// template<> +// struct Mutator::MutationPolicy +// { +// static function +// buildChangeHandler (Duration& target) +// { +// return bind (Mutator::nudgeDuration, ref(target), _1 ); +// } +// }; + + + + + template template void diff --git a/tests/lib/time/time-control-test.cpp b/tests/lib/time/time-control-test.cpp index 032bef1a9..e85fc1685 100644 --- a/tests/lib/time/time-control-test.cpp +++ b/tests/lib/time/time-control-test.cpp @@ -34,6 +34,7 @@ #include #include #include +#include using lib::test::showType; using boost::lexical_cast; @@ -95,28 +96,6 @@ namespace test{ return *received_; } }; - - - - template - struct TestCase - : BASE - { - void - performTestCases(TimeValue const& o, TimeValue const& c) - { - cout << "Test-Case. Target=" << showType() - <<" <--feed--- " << showType() - < KindsOfTarget; - typedef Types KindsOfSource; - typedef InstantiateChainedCombinations< KindsOfTarget - , KindsOfSource - , TestCase - , IterationEnd > TestMatrix; - - TestMatrix().performTestCases(o,c); - } + void verifyMatrix_of_MutationCases (TimeValue const& o, TimeValue const& c); }; + namespace { // Implementation: Matrix of individual test combinations + + template + struct TestTarget + { + static TAR + build (TimeValue const& org) + { + return TAR(org); + } + }; + + template<> + struct TestTarget + { + static TimeSpan + build (TimeValue const& org) + { + return TimeSpan (org, FSecs(3,2)); + } + }; + + template<> + struct TestTarget + { + static QuTime + build (TimeValue const& org) + { + return QuTime (org, "test_grid"); + } + }; + + + template + struct TestChange + { + static SRC + prepareChangeValue (TimeValue const& c) + { + return SRC(c); + } + }; + + template<> + struct TestChange + { + static TimeSpan + prepareChangeValue (TimeValue const& c) + { + return TimeSpan (c, Duration(c)); + } + }; + + template<> + struct TestChange + { + static QuTime + prepareChangeValue (TimeValue const& c) + { + return QuTime (c, "test_grid_NTSC"); + } + }; + + + + template + void + verify_wasChanged (TAR const& target, TimeValue const& org, SRC const& change) + { + CHECK (target != org); + CHECK (target == change); + } + + template + void + verify_wasChanged (Duration const& target, TimeValue const& org, SRC const&) + { + CHECK (target == org, "Logic error: Duration was changed by time value"); + } + void + verify_wasChanged (Duration const& target, TimeValue const& org, Duration const& otherDuration) + { + CHECK (target != org); + CHECK (target == otherDuration); + } + void + verify_wasChanged (Duration const& target, TimeValue const& org, TimeSpan const& span) + { + CHECK (target != org); + CHECK (target == span.duration()); + } + + + + template + void + verify_wasOffset (TAR const&, TimeValue const&, Offset const&)//(TAR const& target, TimeValue const& o, Offset const& offset) + { + + } + + template + void + verify_zeroAlligned (TAR const&, TAR const&)//(TAR const& target, TAR const& oldState) + { + + } + + template + void + verify_nudged (TAR const&, TAR const&, int64_t)//(TAR const& target, TAR const& oldState, int64_t offsetSteps) + { + + } + + + + + template + struct TestCase + : BASE + { + void + performTestCases(TimeValue const& o, TimeValue const& c) + { + cout << "Test-Case. Target=" << showType() + <<" <--feed--- " << showType() + < controller; + + TAR target = TestTarget::build(o); + target.accept (controller); + + SRC change = TestChange::prepareChangeValue(c); + controller (change); + verify_wasChanged (target, o, change); + + Offset offset(c); + controller (offset); + verify_wasOffset (target, o, offset); + + TAR oldState(target); + controller (0); + verify_zeroAlligned(target, oldState); + + controller (+1); + verify_nudged (target, oldState, +1); + + controller (-2); + verify_nudged (target, oldState, -1); + + int maxInt = std::numeric_limits::max(); + int minInt = std::numeric_limits::min(); + + controller (maxInt); + verify_nudged (target, oldState, -1LL + maxInt); + + controller (minInt); + verify_nudged (target, oldState, -1LL + maxInt+minInt); + + + // tail recursion: further test combinations.... + BASE::performTestCases(o,c); + } + }; + + struct IterationEnd + { + void performTestCases(TimeValue const&, TimeValue const&) { } + }; + + }//(End)Implementation Test-case matrix + + + void + TimeControl_test::verifyMatrix_of_MutationCases (TimeValue const& o, TimeValue const& c) + { + typedef Types KindsOfTarget; + typedef Types KindsOfSource; + typedef InstantiateChainedCombinations< KindsOfTarget + , KindsOfSource + , TestCase + , IterationEnd > TestMatrix; + + TestMatrix().performTestCases(o,c); + } + + /** Register this test class... */ LAUNCHER (TimeControl_test, "unit common");