2009-06-08 21:29:09 +02:00
|
|
|
/*
|
|
|
|
|
CommandBasic(Test) - checking simple ProcDispatcher command definition and execution
|
|
|
|
|
|
|
|
|
|
Copyright (C) Lumiera.org
|
|
|
|
|
2009, Hermann Vosseler <Ichthyostega@web.de>
|
|
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
|
|
|
modify it under the terms of the GNU General Public License as
|
|
|
|
|
published by the Free Software Foundation; either version 2 of the
|
|
|
|
|
License, or (at your option) any later version.
|
|
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
|
along with this program; if not, write to the Free Software
|
|
|
|
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
|
|
|
|
|
|
* *****************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "lib/test/run.hpp"
|
2009-06-12 20:10:27 +02:00
|
|
|
#include "lib/test/test-helper.hpp"
|
2009-06-08 21:29:09 +02:00
|
|
|
//#include "proc/asset/media.hpp"
|
|
|
|
|
//#include "proc/mobject/session.hpp"
|
|
|
|
|
//#include "proc/mobject/session/edl.hpp"
|
|
|
|
|
//#include "proc/mobject/session/testclip.hpp"
|
2009-06-10 03:42:23 +02:00
|
|
|
//#include "proc/mobject/test-dummy-mobject.hpp"
|
|
|
|
|
#include "lib/p.hpp"
|
2009-06-08 21:29:09 +02:00
|
|
|
//#include "proc/mobject/placement.hpp"
|
|
|
|
|
//#include "proc/mobject/placement-index.hpp"
|
|
|
|
|
//#include "proc/mobject/explicitplacement.hpp"
|
|
|
|
|
#include "proc/control/command-def.hpp"
|
2009-06-10 05:00:01 +02:00
|
|
|
#include "lib/lumitime.hpp"
|
2009-06-08 21:29:09 +02:00
|
|
|
//#include "lib/util.hpp"
|
|
|
|
|
|
2009-06-10 05:00:01 +02:00
|
|
|
#include "lib/meta/typelist.hpp"
|
|
|
|
|
#include "lib/meta/typelistutil.hpp"
|
2009-06-14 05:38:35 +02:00
|
|
|
#include "lib/meta/generator.hpp"
|
2009-06-10 05:00:01 +02:00
|
|
|
|
2009-06-10 03:42:23 +02:00
|
|
|
#include <tr1/functional>
|
2009-06-08 21:29:09 +02:00
|
|
|
//#include <boost/format.hpp>
|
2009-06-12 20:10:27 +02:00
|
|
|
#include <iostream>
|
2009-06-08 21:29:09 +02:00
|
|
|
#include <string>
|
|
|
|
|
|
2009-06-10 05:00:01 +02:00
|
|
|
using std::tr1::bind;
|
|
|
|
|
//using std::tr1::placeholders::_1;
|
|
|
|
|
//using std::tr1::placeholders::_2;
|
2009-06-10 03:42:23 +02:00
|
|
|
using std::tr1::function;
|
2009-06-08 21:29:09 +02:00
|
|
|
//using boost::format;
|
2009-06-10 05:00:01 +02:00
|
|
|
using lumiera::Time;
|
2009-06-08 21:29:09 +02:00
|
|
|
//using util::contains;
|
|
|
|
|
using std::string;
|
2009-06-12 20:10:27 +02:00
|
|
|
using std::cout;
|
|
|
|
|
using std::endl;
|
2009-06-08 21:29:09 +02:00
|
|
|
|
|
|
|
|
|
2009-06-10 05:00:01 +02:00
|
|
|
namespace lumiera {
|
|
|
|
|
namespace typelist{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////TODO braindump
|
|
|
|
|
|
|
|
|
|
template< typename SIG>
|
|
|
|
|
struct FunctionSignature;
|
|
|
|
|
|
|
|
|
|
template< typename RET>
|
|
|
|
|
struct FunctionSignature< function<RET(void)> >
|
|
|
|
|
{
|
|
|
|
|
typedef RET Ret;
|
|
|
|
|
typedef Types<> Args;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template< typename RET
|
|
|
|
|
, typename A1
|
|
|
|
|
>
|
|
|
|
|
struct FunctionSignature< function<RET(A1)> >
|
|
|
|
|
{
|
|
|
|
|
typedef RET Ret;
|
|
|
|
|
typedef Types<A1> Args;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template< typename RET
|
|
|
|
|
, typename A1
|
|
|
|
|
, typename A2
|
|
|
|
|
>
|
|
|
|
|
struct FunctionSignature< function<RET(A1,A2)> >
|
|
|
|
|
{
|
|
|
|
|
typedef RET Ret;
|
|
|
|
|
typedef Types<A1,A2> Args;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template< typename RET
|
|
|
|
|
, typename A1
|
|
|
|
|
, typename A2
|
|
|
|
|
, typename A3
|
|
|
|
|
>
|
|
|
|
|
struct FunctionSignature< function<RET(A1,A2,A3)> >
|
|
|
|
|
{
|
|
|
|
|
typedef RET Ret;
|
|
|
|
|
typedef Types<A1,A2,A3> Args;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template< typename RET
|
|
|
|
|
, typename A1
|
|
|
|
|
, typename A2
|
|
|
|
|
, typename A3
|
|
|
|
|
, typename A4
|
|
|
|
|
>
|
|
|
|
|
struct FunctionSignature< function<RET(A1,A2,A3,A4)> >
|
|
|
|
|
{
|
|
|
|
|
typedef RET Ret;
|
|
|
|
|
typedef Types<A1,A2,A3,A4> Args;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template< typename RET
|
|
|
|
|
, typename A1
|
|
|
|
|
, typename A2
|
|
|
|
|
, typename A3
|
|
|
|
|
, typename A4
|
|
|
|
|
, typename A5
|
|
|
|
|
>
|
|
|
|
|
struct FunctionSignature< function<RET(A1,A2,A3,A4,A5)> >
|
|
|
|
|
{
|
|
|
|
|
typedef RET Ret;
|
|
|
|
|
typedef Types<A1,A2,A3,A4,A5> Args;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template<typename RET, typename LI>
|
|
|
|
|
struct FunctionTypedef;
|
|
|
|
|
|
|
|
|
|
template< typename RET>
|
|
|
|
|
struct FunctionTypedef<RET, Types<> >
|
|
|
|
|
{
|
|
|
|
|
typedef function<RET(void)> Func;
|
|
|
|
|
typedef RET Sig();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template< typename RET
|
|
|
|
|
, typename A1
|
|
|
|
|
>
|
|
|
|
|
struct FunctionTypedef<RET, Types<A1> >
|
|
|
|
|
{
|
|
|
|
|
typedef function<RET(A1)> Func;
|
|
|
|
|
typedef RET Sig(A1);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template< typename RET
|
|
|
|
|
, typename A1
|
|
|
|
|
, typename A2
|
|
|
|
|
>
|
|
|
|
|
struct FunctionTypedef<RET, Types<A1,A2> >
|
|
|
|
|
{
|
|
|
|
|
typedef function<RET(A1,A2)> Func;
|
|
|
|
|
typedef RET Sig(A1,A2);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template< typename RET
|
|
|
|
|
, typename A1
|
|
|
|
|
, typename A2
|
|
|
|
|
, typename A3
|
|
|
|
|
>
|
|
|
|
|
struct FunctionTypedef<RET, Types<A1,A2,A3> >
|
|
|
|
|
{
|
|
|
|
|
typedef function<RET(A1,A2,A3)> Func;
|
|
|
|
|
typedef RET Sig(A1,A2,A3);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template< typename RET
|
|
|
|
|
, typename A1
|
|
|
|
|
, typename A2
|
|
|
|
|
, typename A3
|
|
|
|
|
, typename A4
|
|
|
|
|
>
|
|
|
|
|
struct FunctionTypedef<RET, Types<A1,A2,A3,A4> >
|
|
|
|
|
{
|
|
|
|
|
typedef function<RET(A1,A2,A3,A4)> Func;
|
|
|
|
|
typedef RET Sig(A1,A2,A3,A4);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template< typename RET
|
|
|
|
|
, typename A1
|
|
|
|
|
, typename A2
|
|
|
|
|
, typename A3
|
|
|
|
|
, typename A4
|
|
|
|
|
, typename A5
|
|
|
|
|
>
|
|
|
|
|
struct FunctionTypedef<RET, Types<A1,A2,A3,A4,A5> >
|
|
|
|
|
{
|
|
|
|
|
typedef function<RET(A1,A2,A3,A4,A5)> Func;
|
|
|
|
|
typedef RET Sig(A1,A2,A3,A4,A5);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2009-06-14 19:40:35 +02:00
|
|
|
/////////////////////////very basic facility: Typed tuples
|
2009-06-10 05:00:01 +02:00
|
|
|
|
|
|
|
|
template<class T, class TYPES>
|
|
|
|
|
struct Prepend;
|
|
|
|
|
|
|
|
|
|
template< typename A1
|
|
|
|
|
, typename A2
|
|
|
|
|
, typename A3
|
|
|
|
|
, typename A4
|
|
|
|
|
, typename A5
|
|
|
|
|
, typename IGN
|
|
|
|
|
>
|
|
|
|
|
struct Prepend<A1, Types<A2,A3,A4,A5,IGN> >
|
|
|
|
|
{
|
|
|
|
|
typedef Types<A1,A2,A3,A4,A5> Tuple;
|
|
|
|
|
};
|
|
|
|
|
|
2009-06-14 19:40:35 +02:00
|
|
|
template<class TYPES>
|
2009-06-10 05:00:01 +02:00
|
|
|
struct Tuple;
|
|
|
|
|
|
|
|
|
|
template<>
|
|
|
|
|
struct Tuple<NullType>
|
|
|
|
|
{
|
2009-06-14 19:40:35 +02:00
|
|
|
typedef NullType HeadType;
|
|
|
|
|
typedef Types<> TailType;
|
|
|
|
|
typedef Types<> Type;
|
|
|
|
|
|
|
|
|
|
typedef NullType ArgList_;
|
|
|
|
|
typedef Tuple<Type> ThisTuple;
|
|
|
|
|
typedef Tuple<NullType> Tail;
|
2009-06-10 05:00:01 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template<class TY, class TYPES>
|
|
|
|
|
struct Tuple<Node<TY,TYPES> >
|
2009-06-14 19:40:35 +02:00
|
|
|
: Tuple<TYPES>
|
2009-06-10 05:00:01 +02:00
|
|
|
{
|
2009-06-14 19:40:35 +02:00
|
|
|
typedef TY HeadType;
|
|
|
|
|
typedef typename Tuple<TYPES>::Type TailType;
|
|
|
|
|
typedef typename Prepend<TY,Tail>::Tuple Type;
|
|
|
|
|
|
|
|
|
|
typedef typename Node<TY,TYPES> ArgList_;
|
|
|
|
|
typedef Tuple<Type> ThisTuple;
|
|
|
|
|
typedef Tuple<TYPES> Tail;
|
|
|
|
|
|
|
|
|
|
Tuple ( TY a1 =TY()
|
|
|
|
|
, Tail tail =Tail()
|
|
|
|
|
)
|
|
|
|
|
: Tuple<TYPES> (tail.getHead(), tail.getTail()),
|
|
|
|
|
val_(a1)
|
|
|
|
|
{ }
|
|
|
|
|
|
|
|
|
|
TY & getHead() { return val_; }
|
|
|
|
|
Tail& getTail() { return static_cast<Tail&> (*this); }
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
T1 val_;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template< typename T1
|
|
|
|
|
, typename T2 =NullType
|
|
|
|
|
, typename T3 =NullType
|
|
|
|
|
, typename T4 =NullType
|
|
|
|
|
, typename T5 =NullType
|
|
|
|
|
>
|
|
|
|
|
struct Tuple<Types<T1,T2,T3,T4,T5> >
|
|
|
|
|
: Tuple<typename Types<T1,T2,T3,T4,T5>::List>
|
|
|
|
|
{
|
|
|
|
|
typedef T1 HeadType;
|
|
|
|
|
typedef Types<T2,T3,T4,T5,NullType> TailType;
|
|
|
|
|
typedef Types<T1,T2,T3,T4,T5> Type;
|
|
|
|
|
|
|
|
|
|
typedef typename Type::List ArgList_;
|
|
|
|
|
typedef Tuple<Type> ThisTuple;
|
|
|
|
|
typedef Tuple<TailType> Tail;
|
|
|
|
|
|
|
|
|
|
Tuple ( T1 a1 =T1()
|
|
|
|
|
, T2 a2 =T2()
|
|
|
|
|
, T3 a3 =T3()
|
|
|
|
|
, T4 a4 =T4()
|
|
|
|
|
, T5 a5 =T5()
|
|
|
|
|
)
|
|
|
|
|
: Tuple<ArgList_>(a1,makeTuple(a2,a3,a4,a5))
|
|
|
|
|
{ }
|
|
|
|
|
|
|
|
|
|
using ArgList_::getHead;
|
|
|
|
|
using ArgList_::getTail;
|
|
|
|
|
|
|
|
|
|
template<uint i> struct Shifted { typedef typename Tail::Shifted<i-1>::Type Tuple; };
|
|
|
|
|
template<> struct Shifted<0>{ typedef ThisTuple Tuple; };
|
|
|
|
|
|
|
|
|
|
template<uint i>
|
|
|
|
|
typename Shifted<i>::Tuple&
|
|
|
|
|
getShifted ()
|
|
|
|
|
{
|
|
|
|
|
typedef typename Shifted<i>::Tuple TailI;
|
|
|
|
|
return static_cast<TailI&> (*this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<uint i>
|
|
|
|
|
typename Shifted<i>::Tuple::HeadType&
|
|
|
|
|
getAt ()
|
|
|
|
|
{
|
|
|
|
|
return getShifted<i>().getHead();
|
|
|
|
|
}
|
2009-06-10 05:00:01 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
2009-06-15 03:47:05 +02:00
|
|
|
/**
|
|
|
|
|
* Decorating a tuple type with auxiliary data access operations.
|
|
|
|
|
* This helper template builds up a subclass of the given BASE type
|
|
|
|
|
* (which is assumed to be a Tuple or at least need to be copy constructible
|
|
|
|
|
* from \c Tuple<TYPES> ). The purpose is to use the Tuple as storage, but
|
|
|
|
|
* to add a layer of access functions, which in turn might rely on the exact
|
|
|
|
|
* type of the individual elements within the Tuple. To achieve this, for each
|
|
|
|
|
* type within the Tuple, the BASE type is decorated with an instance of the
|
|
|
|
|
* template passed in as template template parameter _X_. Each of these
|
|
|
|
|
* decorating instances is provided with a member pointer to access "his"
|
|
|
|
|
* specific element within the underlying tuple.
|
|
|
|
|
*
|
|
|
|
|
* The decorating template _X_ need to take its own base class as template
|
|
|
|
|
* parameter. Typically, operations on _X_ will be defined in a recursive fashion,
|
|
|
|
|
* calling down into this templated base class. To support this, an instantiation
|
|
|
|
|
* of _X_ with the 0 member ptr is generated for detecting recursion end
|
|
|
|
|
* (built as innermost decorator, i.e. immediate subclass of BASE)
|
|
|
|
|
*/
|
|
|
|
|
template
|
|
|
|
|
< typename TYPES
|
|
|
|
|
, template<class TY,class B, TY B::*getter()> class _X_
|
|
|
|
|
, class BASE =Tuple<TYPES>
|
|
|
|
|
>
|
|
|
|
|
class BuildTupleAccessor
|
|
|
|
|
{
|
|
|
|
|
typedef typename Tuple<TYPES> Tuple;
|
|
|
|
|
typedef typename Tuple::TailType Tail;
|
|
|
|
|
typedef typename Tuple::HeadType Head;
|
|
|
|
|
typedef Head Tuple::*getElm();
|
|
|
|
|
typedef BuildTupleAccessor<Tail, _X_> NextBuilder;
|
|
|
|
|
typedef typename NextBuilder::Accessor NextAccessor;
|
|
|
|
|
|
|
|
|
|
Tuple<TYPES>& argData_;
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
|
|
/** type of the product created by this template.
|
|
|
|
|
* Will be a subclass of BASE */
|
|
|
|
|
typedef _X_<Head, NextAccessor, &Tuple::getHead, > Accessor;
|
|
|
|
|
|
|
|
|
|
BuildTupleAccessor (Tuple<TYPES>& tup)
|
|
|
|
|
: argData_(tup)
|
|
|
|
|
{ }
|
|
|
|
|
|
|
|
|
|
operator Accessor() { return Accessor(argData_); }
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template
|
|
|
|
|
< class BASE
|
|
|
|
|
, template<class,class> class _X_
|
|
|
|
|
>
|
|
|
|
|
class BuildTupleAccessor<Tuple<Types<> >, _X_>
|
|
|
|
|
{
|
|
|
|
|
typedef typename Tuple<Types<> > Tuple;
|
|
|
|
|
typedef NullType Tuple::*getElm();
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
typedef _X_<NullType, BASE, 0> Accessor;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
///////////////////////// creating functional closures
|
|
|
|
|
|
|
|
|
|
namespace tuple {
|
|
|
|
|
template<uint n>
|
|
|
|
|
struct Apply;
|
|
|
|
|
|
|
|
|
|
template<>
|
|
|
|
|
struct Apply<1>
|
|
|
|
|
{
|
|
|
|
|
template<class FUN, typename RET, class TUP>
|
|
|
|
|
static RET
|
|
|
|
|
invoke (FUN f, TUP & arg)
|
|
|
|
|
{
|
|
|
|
|
return f (arg.getAt<1>());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<class FUN, typename RET, class TUP>
|
|
|
|
|
static RET
|
|
|
|
|
bind (FUN f, TUP & arg)
|
|
|
|
|
{
|
|
|
|
|
return std::tr1::bind (f, arg.getAt<1>());
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template<>
|
|
|
|
|
struct Apply<2>
|
|
|
|
|
{
|
|
|
|
|
template<class FUN, typename RET, class TUP>
|
|
|
|
|
static RET
|
|
|
|
|
invoke (FUN f, TUP & arg)
|
|
|
|
|
{
|
|
|
|
|
return f ( arg.getAt<1>()
|
|
|
|
|
, arg.getAt<2>()
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<class FUN, typename RET, class TUP>
|
|
|
|
|
static RET
|
|
|
|
|
bind (FUN f, TUP & arg)
|
|
|
|
|
{
|
|
|
|
|
return std::tr1::bind (f, arg.getAt<1>()
|
|
|
|
|
, arg.getAt<2>()
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
} // (END) sub-namespace
|
|
|
|
|
|
|
|
|
|
template<typename SIG>
|
|
|
|
|
class TupleApplicator
|
|
|
|
|
{
|
|
|
|
|
typedef typename FunctionSignature< function<SIG> >::Args Args;
|
|
|
|
|
typedef typename FunctionSignature< function<SIG> >::Ret Ret;
|
|
|
|
|
|
|
|
|
|
enum { ARG_CNT = count<Args::List>::value };
|
|
|
|
|
|
|
|
|
|
using tuple::Apply;
|
|
|
|
|
|
|
|
|
|
/** storing a ref to the parameter tuple */
|
|
|
|
|
Tuple<Args>& params_;
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
TupleApplicator (Tuple<Args>& args)
|
|
|
|
|
: params_(args)
|
|
|
|
|
{ }
|
|
|
|
|
|
|
|
|
|
function<SIG> bind (SIG& f) { return Apply<ARG_CNT>::bind (f, params_); }
|
|
|
|
|
function<SIG> bind (function<SIG> const& f) { return Apply<ARG_CNT>::bind (f, params_); }
|
|
|
|
|
|
|
|
|
|
Ret operator() (SIG& f) { return Apply<ARG_CNT>::invoke (f, params_); }
|
|
|
|
|
Ret operator() (function<SIG> const& f) { return Apply<ARG_CNT>::invoke (f, params_); }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Closing a function over its arguments.
|
|
|
|
|
* This is a small usage example or spin-off,
|
|
|
|
|
* having almost the same effect than invoking tr1::bind.
|
|
|
|
|
* The notable difference is that the function arguments for
|
|
|
|
|
* creating the closure are passed in as one compound tuple.
|
|
|
|
|
*/
|
|
|
|
|
template<typename SIG>
|
|
|
|
|
class FunctionClosure
|
|
|
|
|
{
|
|
|
|
|
typedef typename FunctionSignature< function<SIG> >::Args Args;
|
|
|
|
|
typedef typename FunctionSignature< function<SIG> >::Ret Ret;
|
|
|
|
|
|
|
|
|
|
function<Ret(void)> closure_;
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
FunctionClosure (SIG& f, Tuple<Args>& arg)
|
|
|
|
|
: closure_(TupleApplicator<SIG>(arg).bind(f))
|
|
|
|
|
{ }
|
|
|
|
|
FunctionClosure (function<SIG> const& f, Tuple<Args>& arg)
|
|
|
|
|
: closure_(TupleApplicator<SIG>(arg).bind(f))
|
|
|
|
|
{ }
|
|
|
|
|
|
|
|
|
|
Ret operator() () { return closure_(); }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
template<typename TYPES>
|
|
|
|
|
struct BuildClosure
|
|
|
|
|
: InstantiateWithIndex<TYPES, Accessor, I>
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
*/
|
|
|
|
|
|
2009-06-14 19:40:35 +02:00
|
|
|
///////////////////////// additional typelist manipulators
|
|
|
|
|
|
2009-06-12 19:49:44 +02:00
|
|
|
template<class TYPES>
|
|
|
|
|
struct SplitLast;
|
|
|
|
|
|
|
|
|
|
template<>
|
|
|
|
|
struct SplitLast<NullType>
|
|
|
|
|
{
|
|
|
|
|
typedef NullType Type;
|
|
|
|
|
typedef NullType Prefix;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template<class TY>
|
|
|
|
|
struct SplitLast<Node<TY,NullType> >
|
|
|
|
|
{
|
|
|
|
|
typedef TY Type;
|
|
|
|
|
typedef NullType Prefix;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template<class TY, class TYPES>
|
|
|
|
|
struct SplitLast<Node<TY,TYPES> >
|
|
|
|
|
{
|
|
|
|
|
typedef typename SplitLast<TYPES>::Type Type;
|
|
|
|
|
typedef typename Append<TY, typename SplitLast<TYPES>::Prefix>::List Prefix;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
2009-06-10 05:00:01 +02:00
|
|
|
|
|
|
|
|
}} // namespace lumiera::typelist
|
|
|
|
|
|
2009-06-08 21:29:09 +02:00
|
|
|
namespace control {
|
|
|
|
|
namespace test {
|
|
|
|
|
|
2009-06-12 20:10:27 +02:00
|
|
|
using lib::test::showSizeof;
|
|
|
|
|
|
2009-06-08 21:29:09 +02:00
|
|
|
// using session::test::TestClip;
|
2009-06-10 05:00:01 +02:00
|
|
|
using lumiera::P;
|
2009-06-10 03:42:23 +02:00
|
|
|
|
2009-06-10 05:00:01 +02:00
|
|
|
using lumiera::typelist::FunctionSignature;
|
|
|
|
|
using lumiera::typelist::FunctionTypedef;
|
|
|
|
|
|
2009-06-14 05:38:35 +02:00
|
|
|
using lumiera::typelist::Types;
|
|
|
|
|
using lumiera::typelist::NullType;
|
2009-06-10 05:00:01 +02:00
|
|
|
using lumiera::typelist::Tuple;
|
|
|
|
|
using lumiera::typelist::Append;
|
2009-06-12 19:49:44 +02:00
|
|
|
using lumiera::typelist::SplitLast;
|
2009-06-10 03:42:23 +02:00
|
|
|
|
2009-06-15 03:47:05 +02:00
|
|
|
using lumiera::typelist::BuildTupleAccessor;
|
2009-06-08 21:29:09 +02:00
|
|
|
|
2009-06-12 19:49:44 +02:00
|
|
|
/**
|
|
|
|
|
* Type analysis helper template.
|
|
|
|
|
* Used for dissecting a given type signature to derive
|
|
|
|
|
* the related basic operation signature, the signature of a possible Undo-function
|
|
|
|
|
* and the signature necessary for capturing undo information. The implementation
|
|
|
|
|
* relies on re-binding an embedded type defining template, based on the actual
|
|
|
|
|
* case, as identified by the structure of the given parameter signature.
|
|
|
|
|
*/
|
|
|
|
|
template<typename SIG>
|
|
|
|
|
struct UndoSignature
|
2009-06-10 03:42:23 +02:00
|
|
|
{
|
2009-06-12 19:49:44 +02:00
|
|
|
private:
|
|
|
|
|
typedef typename FunctionSignature< function<SIG> >::Args Args;
|
|
|
|
|
typedef typename FunctionSignature< function<SIG> >::Ret Ret;
|
|
|
|
|
|
|
|
|
|
/** Case1: defining the Undo-Capture function */
|
|
|
|
|
template<typename RET, typename ARG>
|
|
|
|
|
struct Case
|
|
|
|
|
{
|
|
|
|
|
typedef RET Memento;
|
|
|
|
|
typedef typename Append<ARG, Memento>::List ExtendedArglist;
|
|
|
|
|
typedef typename Tuple<ExtendedArglist>::Type ExtendedArgs;
|
|
|
|
|
|
|
|
|
|
typedef typename FunctionTypedef<void, ARG>::Sig OperateSig;
|
|
|
|
|
typedef typename FunctionTypedef<Ret,ARG>::Sig CaptureSig;
|
|
|
|
|
typedef typename FunctionTypedef<void, ExtendedArgs>::Sig UndoOp_Sig;
|
|
|
|
|
};
|
|
|
|
|
/** Case2: defining the actual Undo function */
|
|
|
|
|
template<typename ARG>
|
|
|
|
|
struct Case<void,ARG>
|
|
|
|
|
{
|
|
|
|
|
typedef typename ARG::List Args;
|
|
|
|
|
|
|
|
|
|
typedef typename SplitLast<Args>::Type Memento;
|
|
|
|
|
typedef typename SplitLast<Args>::Prefix OperationArglist;
|
|
|
|
|
typedef typename Tuple<OperationArglist>::Type OperationArgs;
|
|
|
|
|
|
|
|
|
|
typedef typename FunctionTypedef<void, OperationArgs>::Sig OperateSig;
|
|
|
|
|
typedef typename FunctionTypedef<Ret,OperationArgs>::Sig CaptureSig;
|
|
|
|
|
typedef typename FunctionTypedef<void, ARG>::Sig UndoOp_Sig;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
typedef typename Case<Ret,Args>::CaptureSig CaptureSig;
|
|
|
|
|
typedef typename Case<Ret,Args>::UndoOp_Sig UndoOp_Sig;
|
|
|
|
|
typedef typename Case<Ret,Args>::OperateSig OperateSig;
|
|
|
|
|
typedef typename Case<Ret,Args>::Memento Memento;
|
2009-06-10 03:42:23 +02:00
|
|
|
};
|
2009-06-12 20:21:46 +02:00
|
|
|
|
2009-06-10 03:42:23 +02:00
|
|
|
|
2009-06-10 05:00:01 +02:00
|
|
|
|
2009-06-14 05:38:35 +02:00
|
|
|
|
2009-06-15 03:47:05 +02:00
|
|
|
|
|
|
|
|
/** Interface */
|
|
|
|
|
class CmdClosure
|
2009-06-14 05:38:35 +02:00
|
|
|
{
|
2009-06-15 03:47:05 +02:00
|
|
|
public:
|
|
|
|
|
virtual ~CmdClosure() {}
|
2009-06-14 05:38:35 +02:00
|
|
|
};
|
|
|
|
|
|
2009-06-15 03:47:05 +02:00
|
|
|
|
|
|
|
|
template<typename TY, class BASE, TY BASE::*getElm()>
|
|
|
|
|
struct ParamAccessor
|
2009-06-14 05:38:35 +02:00
|
|
|
{
|
|
|
|
|
|
|
|
|
|
};
|
2009-06-15 03:47:05 +02:00
|
|
|
template<class BASE>
|
|
|
|
|
struct ParamAccessor<NullType, BASE, 0>
|
2009-06-14 05:38:35 +02:00
|
|
|
{
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
2009-06-15 03:47:05 +02:00
|
|
|
template<typename SIG>
|
|
|
|
|
class Closure
|
|
|
|
|
: public CmdClosure
|
2009-06-14 05:38:35 +02:00
|
|
|
{
|
2009-06-15 03:47:05 +02:00
|
|
|
typedef typename FunctionSignature< function<SIG> >::Args Args;
|
|
|
|
|
// typedef typename FunctionSignature< function<SIG> >::Ret Ret;
|
|
|
|
|
|
|
|
|
|
typedef Tuple<Arg> ArgTuple;
|
|
|
|
|
|
|
|
|
|
typedef BuildTupleAccessor<Args,ParamAccessor> BuildAccessor;
|
|
|
|
|
typedef typename BuildAccessor::Accessor ParamStorageTuple;
|
|
|
|
|
|
|
|
|
|
ParamStorageTuple params_;
|
|
|
|
|
|
|
|
|
|
Closure (ArgTuple& args)
|
|
|
|
|
: params_(BuildAccessor(args))
|
|
|
|
|
{ }
|
2009-06-14 05:38:35 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
2009-06-12 20:21:46 +02:00
|
|
|
|
2009-06-15 03:47:05 +02:00
|
|
|
|
2009-06-12 20:21:46 +02:00
|
|
|
/**
|
|
|
|
|
* Helper class used solely for \em defining a Command-Object.
|
|
|
|
|
* This technique is known as "fluent API", see http://en.wikipedia.org/wiki/Fluent_interface
|
|
|
|
|
* The basic idea is for the user to create a disposable instance of this definition helper,
|
|
|
|
|
* only for calling a chain of definition functions, which internally build the actual Command object.
|
|
|
|
|
* Finally, the created Command object will be stored into a registry or handed over to the
|
|
|
|
|
* ProcDispatcher. To give an example:
|
|
|
|
|
* \code
|
|
|
|
|
* CommandDefinition ("test.command1")
|
|
|
|
|
* .operation (command1::operate) // provide the function to be executed as command
|
|
|
|
|
* .captureUndo (command1::capture) // provide the function capturing Undo state
|
2009-06-14 05:38:35 +02:00
|
|
|
* .undoOperation (command1::undoIt) // provide the function which might undo the command
|
2009-06-12 20:21:46 +02:00
|
|
|
* .bind (obj, randVal) // bind to the actual command parameters
|
|
|
|
|
* .executeSync(); // convenience call, forwarding the Command to dispatch.
|
|
|
|
|
* \endcode
|
|
|
|
|
*
|
|
|
|
|
* @todo of course, this needs to be extracted into command-definition.hpp
|
|
|
|
|
*/
|
2009-06-10 03:42:23 +02:00
|
|
|
class CommDef
|
|
|
|
|
{
|
|
|
|
|
Symbol id_;
|
|
|
|
|
|
|
|
|
|
template<typename SIG, typename MEM>
|
|
|
|
|
struct UndoDefinition
|
|
|
|
|
{
|
2009-06-12 20:10:27 +02:00
|
|
|
typedef typename FunctionSignature< function<SIG> >::Args BasicArgs;
|
|
|
|
|
typedef typename FunctionTypedef<MEM,BasicArgs>::Sig UndoCaptureSig;
|
|
|
|
|
|
|
|
|
|
UndoDefinition (function<UndoCaptureSig>& undoCapOperation)
|
|
|
|
|
{
|
|
|
|
|
cout << showSizeof(undoCapOperation) << endl;
|
|
|
|
|
UNIMPLEMENTED ("re-fetch command definition and augment it with Functor for capturing Undo information");
|
|
|
|
|
}
|
2009-06-10 05:00:01 +02:00
|
|
|
|
2009-06-12 19:49:44 +02:00
|
|
|
template<typename SIG2>
|
2009-06-12 20:10:27 +02:00
|
|
|
UndoDefinition&
|
2009-06-12 19:49:44 +02:00
|
|
|
undoOperation (SIG2& how_to_Undo)
|
2009-06-10 03:42:23 +02:00
|
|
|
{
|
2009-06-12 19:49:44 +02:00
|
|
|
typedef typename UndoSignature<SIG2>::UndoOp_Sig UndoSig;
|
|
|
|
|
|
2009-06-10 05:00:01 +02:00
|
|
|
function<UndoSig> opera3 (how_to_Undo);
|
2009-06-10 03:42:23 +02:00
|
|
|
|
2009-06-12 20:10:27 +02:00
|
|
|
UNIMPLEMENTED ("store actual Undo-Functor into the command definition held by the enclosing UndoDefinition instance");
|
|
|
|
|
return *this;
|
2009-06-10 03:42:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
2009-06-12 19:49:44 +02:00
|
|
|
/** type re-binding helper: create a suitable UndoDefinition type,
|
|
|
|
|
* based on the UndoSignature template instance given as parameter */
|
|
|
|
|
template<typename U_SIG>
|
|
|
|
|
struct BuildUndoDefType
|
|
|
|
|
{
|
|
|
|
|
typedef UndoDefinition<typename U_SIG::OperateSig, typename U_SIG::Memento> Type;
|
|
|
|
|
};
|
|
|
|
|
|
2009-06-10 03:42:23 +02:00
|
|
|
template<typename SIG>
|
|
|
|
|
struct BasicDefinition
|
|
|
|
|
{
|
2009-06-12 20:10:27 +02:00
|
|
|
BasicDefinition(function<SIG>& operation)
|
|
|
|
|
{
|
|
|
|
|
cout << showSizeof(operation) << endl;
|
|
|
|
|
UNIMPLEMENTED ("create new command object an store the operation functor");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2009-06-12 19:49:44 +02:00
|
|
|
template<typename SIG2>
|
|
|
|
|
typename BuildUndoDefType<UndoSignature<SIG2> >::Type
|
|
|
|
|
captureUndo (SIG2& how_to_capture_UndoState)
|
2009-06-10 03:42:23 +02:00
|
|
|
{
|
2009-06-12 19:49:44 +02:00
|
|
|
typedef typename UndoSignature<SIG2>::CaptureSig UndoCapSig;
|
2009-06-12 20:10:27 +02:00
|
|
|
typedef typename BuildUndoDefType<UndoSignature<SIG2> >::Type SpecificUndoDefinition;
|
2009-06-10 05:00:01 +02:00
|
|
|
|
|
|
|
|
function<UndoCapSig> opera2 (how_to_capture_UndoState);
|
2009-06-12 20:10:27 +02:00
|
|
|
return SpecificUndoDefinition (opera2);
|
2009-06-10 03:42:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
CommDef (Symbol cmdID)
|
|
|
|
|
: id_(cmdID)
|
|
|
|
|
{ }
|
|
|
|
|
|
|
|
|
|
template<typename SIG>
|
|
|
|
|
BasicDefinition<SIG>
|
2009-06-10 05:00:01 +02:00
|
|
|
operation (SIG& operation_to_define)
|
2009-06-10 03:42:23 +02:00
|
|
|
{
|
2009-06-10 05:00:01 +02:00
|
|
|
function<SIG> opera1 (operation_to_define);
|
2009-06-12 20:10:27 +02:00
|
|
|
return BasicDefinition<SIG>(opera1);
|
2009-06-10 03:42:23 +02:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/////////////////////////////
|
|
|
|
|
/////////////////////////////
|
2009-06-12 20:10:27 +02:00
|
|
|
|
|
|
|
|
//////////////////////////// start of the actual Test....
|
|
|
|
|
|
2009-06-10 03:42:23 +02:00
|
|
|
|
2009-06-09 09:05:19 +02:00
|
|
|
/*
|
|
|
|
|
bind: opFunc(a,b,c) -> op(void)
|
|
|
|
|
|
|
|
|
|
curry(opFunc) (a) (b) (c)
|
|
|
|
|
|
|
|
|
|
pAppl(func, x) -> func2 (b, c)
|
|
|
|
|
|
|
|
|
|
return bind( recursion(), param)
|
|
|
|
|
|
|
|
|
|
*/
|
2009-06-10 03:42:23 +02:00
|
|
|
namespace command1 {
|
|
|
|
|
void
|
2009-06-10 05:00:01 +02:00
|
|
|
operate (P<Time> dummyObj, int randVal)
|
2009-06-10 03:42:23 +02:00
|
|
|
{
|
2009-06-10 05:00:01 +02:00
|
|
|
*dummyObj += Time(randVal);
|
2009-06-10 03:42:23 +02:00
|
|
|
}
|
|
|
|
|
|
2009-06-10 05:00:01 +02:00
|
|
|
Time
|
|
|
|
|
capture (P<Time> dummyObj, int)
|
2009-06-10 03:42:23 +02:00
|
|
|
{
|
|
|
|
|
return *dummyObj;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2009-06-10 05:00:01 +02:00
|
|
|
undoIt (P<Time> dummyObj, int, Time oldVal)
|
2009-06-10 03:42:23 +02:00
|
|
|
{
|
|
|
|
|
*dummyObj = oldVal;
|
|
|
|
|
}
|
2009-06-08 21:29:09 +02:00
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2009-06-10 03:42:23 +02:00
|
|
|
////////////////////////////////////////////TODO braindump
|
2009-06-08 21:29:09 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
|
|
|
* @test basic usage of the Proc-Layer command dispatch system.
|
|
|
|
|
* Shows how to define a simple command inline and another
|
|
|
|
|
* simple command as dedicated class. Finally triggers
|
|
|
|
|
* execution of both commands and verifies the command
|
|
|
|
|
* action has been invoked.
|
|
|
|
|
*
|
|
|
|
|
* @todo currently rather a scrapbook for trying out first ideas on the command system !!!!!!!!!!!!!!!
|
|
|
|
|
*
|
|
|
|
|
* @see control::Command
|
|
|
|
|
* @see control::CommandDef
|
|
|
|
|
* @see mobject::ProcDispatcher
|
|
|
|
|
*/
|
|
|
|
|
class CommandBasic_test : public Test
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
virtual void
|
|
|
|
|
run (Arg)
|
|
|
|
|
{
|
|
|
|
|
/////////////////////////////////TODO
|
|
|
|
|
}
|
|
|
|
|
|
2009-06-10 03:42:23 +02:00
|
|
|
void
|
|
|
|
|
defineCommands ()
|
|
|
|
|
{
|
|
|
|
|
CommDef ("test.command1")
|
2009-06-10 05:00:01 +02:00
|
|
|
.operation (command1::operate)
|
2009-06-12 19:49:44 +02:00
|
|
|
.captureUndo (command1::capture)
|
2009-06-10 05:00:01 +02:00
|
|
|
.undoOperation (command1::undoIt)
|
|
|
|
|
// .bind (obj, randVal)
|
2009-06-10 03:42:23 +02:00
|
|
|
;
|
|
|
|
|
}
|
|
|
|
|
|
2009-06-08 21:29:09 +02:00
|
|
|
void
|
|
|
|
|
checkExecution ()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** Register this test class... */
|
|
|
|
|
LAUNCHER (CommandBasic_test, "unit controller");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}} // namespace control::test
|