Refactorings regarding use of smart-ptr, Placement and BuilderTool
This commit is contained in:
parent
3e8996005e
commit
6b1be6b7e7
49 changed files with 1329 additions and 236 deletions
168
src/common/accesscasted.hpp
Normal file
168
src/common/accesscasted.hpp
Normal file
|
|
@ -0,0 +1,168 @@
|
|||
/*
|
||||
ACCESSCASTED.hpp - util template to access a value using conversion or cast as appropriate
|
||||
|
||||
Copyright (C) Lumiera.org
|
||||
2008, 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.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/** @file accesscasted.hpp
|
||||
** Helper for accessing a value employing either conversion or downcast
|
||||
** depending on the relation of the source type (type of the original value)
|
||||
** and the target type (type we need within the usage context).
|
||||
** When instantiating AcessCasted<TAR>, we get a template static function
|
||||
** \c AcessCasted<TAR>::access<SRC>(SRC& elm), but the actual implementation
|
||||
** is choosed using boost::type_traits. If no viable implementatino can be
|
||||
** selected, \c EmptyVal<TAR>::create() is invoked instead, which by default
|
||||
** creates a NULL value or similar by using the no-argument ctor of the
|
||||
** type TAR. Alternatively, you may define an specialisation fo EmptyVal,
|
||||
** e.g. throwing an exception instead of creating a NULL value.
|
||||
**
|
||||
** @see lumiera::WrapperPtr usage example to access a variant record
|
||||
**
|
||||
*/
|
||||
|
||||
|
||||
#ifndef UTIL_ACCESSCASTED_H
|
||||
#define UTIL_ACCESSCASTED_H
|
||||
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/type_traits/remove_pointer.hpp>
|
||||
#include <boost/type_traits/remove_reference.hpp>
|
||||
#include <boost/type_traits/is_convertible.hpp>
|
||||
#include <boost/type_traits/is_polymorphic.hpp>
|
||||
#include <boost/type_traits/is_base_of.hpp>
|
||||
|
||||
|
||||
|
||||
namespace util {
|
||||
using boost::remove_pointer;
|
||||
using boost::remove_reference;
|
||||
using boost::is_convertible;
|
||||
using boost::is_polymorphic;
|
||||
using boost::is_base_of;
|
||||
using boost::enable_if;
|
||||
|
||||
|
||||
template <typename SRC, typename TAR>
|
||||
struct can_cast : boost::false_type {};
|
||||
|
||||
template <typename SRC, typename TAR>
|
||||
struct can_cast<SRC*,TAR*> { enum { value = is_base_of<SRC,TAR>::value };};
|
||||
|
||||
template <typename SRC, typename TAR>
|
||||
struct can_cast<SRC*&,TAR*> { enum { value = is_base_of<SRC,TAR>::value };};
|
||||
|
||||
template <typename SRC, typename TAR>
|
||||
struct can_cast<SRC&,TAR&> { enum { value = is_base_of<SRC,TAR>::value };};
|
||||
|
||||
|
||||
template <typename T>
|
||||
struct has_RTTI
|
||||
{
|
||||
typedef typename remove_pointer<
|
||||
typename remove_reference<T>::type>::type TPlain;
|
||||
|
||||
enum { value = is_polymorphic<TPlain>::value };
|
||||
};
|
||||
|
||||
template <typename SRC, typename TAR>
|
||||
struct use_dynamic_downcast
|
||||
{
|
||||
enum { value = can_cast<SRC,TAR>::value
|
||||
&& has_RTTI<SRC>::value
|
||||
&& has_RTTI<TAR>::value
|
||||
};
|
||||
};
|
||||
|
||||
template <typename SRC, typename TAR>
|
||||
struct use_static_downcast
|
||||
{
|
||||
enum { value = can_cast<SRC,TAR>::value
|
||||
&& ( !has_RTTI<SRC>::value
|
||||
|| !has_RTTI<TAR>::value
|
||||
)
|
||||
};
|
||||
};
|
||||
|
||||
template <typename SRC, typename TAR>
|
||||
struct use_conversion
|
||||
{
|
||||
enum { value = is_convertible<SRC,TAR>::value
|
||||
&& !( use_static_downcast<SRC,TAR>::value
|
||||
||use_dynamic_downcast<SRC,TAR>::value
|
||||
)
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
||||
template<typename X>
|
||||
struct EmptyVal
|
||||
{
|
||||
static X create() { return X(); }
|
||||
};
|
||||
template<typename X>
|
||||
struct EmptyVal<X*&>
|
||||
{
|
||||
static X*& create() { static X* nullP(0); return nullP; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template<typename RET>
|
||||
struct NullAccessor
|
||||
{
|
||||
typedef RET Ret;
|
||||
|
||||
static RET access (...) { return ifEmpty(); }
|
||||
static RET ifEmpty () { return EmptyVal<RET>::create(); }
|
||||
};
|
||||
|
||||
template<typename TAR>
|
||||
struct AccessCasted : NullAccessor<TAR>
|
||||
{
|
||||
using NullAccessor<TAR>::access;
|
||||
|
||||
template<typename ELM>
|
||||
static typename enable_if< use_dynamic_downcast<ELM&,TAR>, TAR>::type
|
||||
access (ELM& elem)
|
||||
{
|
||||
return dynamic_cast<TAR> (elem);
|
||||
}
|
||||
|
||||
template<typename ELM>
|
||||
static typename enable_if< use_static_downcast<ELM&,TAR>, TAR>::type
|
||||
access (ELM& elem)
|
||||
{
|
||||
return static_cast<TAR> (elem);
|
||||
}
|
||||
|
||||
template<typename ELM>
|
||||
static typename enable_if< use_conversion<ELM&,TAR>, TAR>::type
|
||||
access (ELM& elem)
|
||||
{
|
||||
return elem;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // namespace util
|
||||
#endif
|
||||
|
|
@ -46,6 +46,7 @@
|
|||
#ifndef LUMIERA_CONFIGRULES_H
|
||||
#define LUMIERA_CONFIGRULES_H
|
||||
|
||||
#include "common/p.hpp"
|
||||
#include "common/query.hpp"
|
||||
#include "common/typelistutil.hpp"
|
||||
#include "common/singletonsubclass.hpp"
|
||||
|
|
@ -57,14 +58,13 @@
|
|||
#include "proc/asset/track.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <tr1/memory>
|
||||
|
||||
|
||||
|
||||
namespace lumiera
|
||||
{
|
||||
using std::string;
|
||||
using std::tr1::shared_ptr;
|
||||
using lumiera::P;
|
||||
|
||||
|
||||
|
||||
|
|
@ -148,13 +148,13 @@ namespace lumiera
|
|||
* @query any goals to be fulfilled by the solution.
|
||||
* @return false if resolution failed. In this case, solution ptr is empty.
|
||||
*/
|
||||
virtual bool resolve (shared_ptr<TY>& solution, const Query<TY>& q) = 0;
|
||||
virtual bool resolve (P<TY>& solution, const Query<TY>& q) = 0;
|
||||
};
|
||||
|
||||
// TODO: the Idea is to provide specialisations for the concrete types
|
||||
// we want to participate in the ConfigRules system....
|
||||
// Thus we get the possibility to create a specific return type,
|
||||
// e.g. return a shared_ptr<Pipe> but a Placement<Track>, using the appropriate factory.
|
||||
// e.g. return a P<Pipe> but a Placement<Track>, using the appropriate factory.
|
||||
// Of course then the definitions need to be split up in separate headers.
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ namespace lumiera
|
|||
|
||||
/** a traits-class to define the smart-ptr to wrap the result */
|
||||
template<class TY>
|
||||
struct WrapReturn { typedef shared_ptr<TY> Wrapper; };
|
||||
struct WrapReturn { typedef P<TY> Wrapper; };
|
||||
|
||||
template<>
|
||||
struct WrapReturn<ProcPatt> { typedef PProcPatt Wrapper; };
|
||||
|
|
|
|||
|
|
@ -40,7 +40,10 @@ This code is heavily inspired by
|
|||
|
||||
/** @file typelistutil.hpp
|
||||
** Helpers for working with lumiera::typelist::Types (i.e. lists-of-types).
|
||||
**
|
||||
** The main purpose is to build interfaces and polymorphic implementations
|
||||
** (using virtual functions) based on templated Types or Collections of types,
|
||||
** which is not possible without Template Metaprogrmming.
|
||||
**
|
||||
** @see lumiera::query::ConfigRules usage example
|
||||
** @see typelist.hpp
|
||||
**
|
||||
|
|
@ -136,11 +139,99 @@ namespace lumiera
|
|||
>
|
||||
{
|
||||
public:
|
||||
typedef InstantiateChained<TYPES,_X_> Next;
|
||||
typedef InstantiateChained<TYPES,_X_,BASE> Next;
|
||||
typedef _X_<TY,Next> Unit;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* A Variation of InstantiateChained providing an incremented
|
||||
* Index value template parameter. This index can e.g. be used
|
||||
* to store pointers in a dispatcher table in the Base class.
|
||||
* Similar to InstantiateChained, this template builds a linear
|
||||
* chain of inheritance. The user-provided template, which is
|
||||
* to be instantiated for all types in the Typelist, now has to
|
||||
* accept an additional third parameter (uint i).
|
||||
*/
|
||||
template
|
||||
< class TYPES // List of Types
|
||||
, template<class,class,uint> class _X_ // your-template-goes-here
|
||||
, class BASE = NullType // Base class at end of chain
|
||||
, uint i = 0 // incremented on each instantiaton
|
||||
>
|
||||
class InstantiateWithIndex;
|
||||
|
||||
|
||||
template< template<class,class,uint> class _X_
|
||||
, class BASE
|
||||
, uint i
|
||||
>
|
||||
class InstantiateWithIndex<NullType, _X_, BASE, i>
|
||||
: public BASE
|
||||
{
|
||||
public:
|
||||
typedef BASE Unit;
|
||||
typedef NullType Next;
|
||||
enum{ COUNT = i };
|
||||
};
|
||||
|
||||
|
||||
template
|
||||
< class TY, typename TYPES
|
||||
, template<class,class,uint> class _X_
|
||||
, class BASE
|
||||
, uint i
|
||||
>
|
||||
class InstantiateWithIndex<Node<TY, TYPES>, _X_, BASE, i>
|
||||
: public _X_< TY
|
||||
, InstantiateWithIndex<TYPES, _X_, BASE, i+1 >
|
||||
, i
|
||||
>
|
||||
{
|
||||
public:
|
||||
typedef InstantiateWithIndex<TYPES,_X_,BASE,i+1> Next;
|
||||
typedef _X_<TY,Next,i> Unit;
|
||||
enum{ COUNT = Next::COUNT };
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Metafunction counting the number of Types in the collection
|
||||
*/
|
||||
template<class TYPES>
|
||||
struct count;
|
||||
template<>
|
||||
struct count<NullType>
|
||||
{
|
||||
enum{ value = 0 };
|
||||
};
|
||||
template<class TY, class TYPES>
|
||||
struct count<Node<TY,TYPES> >
|
||||
{
|
||||
enum{ value = 1 + count<TYPES>::value };
|
||||
};
|
||||
|
||||
/**
|
||||
* Metafunction " max( sizeof(T) ) for T in TYPES "
|
||||
*/
|
||||
template<class TYPES>
|
||||
struct maxSize;
|
||||
template<>
|
||||
struct maxSize<NullType>
|
||||
{
|
||||
enum{ value = 0 };
|
||||
};
|
||||
template<class TY, class TYPES>
|
||||
struct maxSize<Node<TY,TYPES> >
|
||||
{
|
||||
enum{ thisval = sizeof(TY)
|
||||
, nextval = maxSize<TYPES>::value
|
||||
, value = nextval > thisval? nextval:thisval
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
} // namespace typelist
|
||||
|
||||
} // namespace lumiera
|
||||
|
|
|
|||
276
src/common/variant.hpp
Normal file
276
src/common/variant.hpp
Normal file
|
|
@ -0,0 +1,276 @@
|
|||
/*
|
||||
VARIANT.hpp - simple variant wrapper (typesafe union)
|
||||
|
||||
Copyright (C) Lumiera.org
|
||||
2008, 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.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/** @file variant.hpp
|
||||
** This file defines a simple alternative to boost::variant.
|
||||
** It pulls in fewer headers and has a shorter code path, but also
|
||||
** doesn't deal with alignement issues and is <b>not threadsafe</b>.
|
||||
**
|
||||
** Values can be stored using \c operator= . In order to access the value
|
||||
** stored in lumiera::Variant, you additionally need to define a "functor"
|
||||
** <ul><li>with a typedef "Ret" for the return type</li>
|
||||
** <li>providing a <tt>static Ret access(ELM&)</tt> function
|
||||
** for each of the types used in the Variant</li>
|
||||
** </ul>
|
||||
**
|
||||
** @see wrapperptr.hpp usage example
|
||||
*/
|
||||
|
||||
|
||||
#ifndef LUMIERA_VARIANT_H
|
||||
#define LUMIERA_VARIANT_H
|
||||
|
||||
|
||||
#include "common/typelistutil.hpp"
|
||||
|
||||
#include <boost/noncopyable.hpp>
|
||||
|
||||
|
||||
|
||||
namespace lumiera {
|
||||
|
||||
namespace variant {
|
||||
|
||||
using lumiera::typelist::count;
|
||||
using lumiera::typelist::maxSize;
|
||||
using lumiera::typelist::InstantiateWithIndex;
|
||||
|
||||
/**
|
||||
* internal helper used to build a variant storage wrapper.
|
||||
* Parametrized with a collection of types, it provides functionality
|
||||
* to copy a value of one of these types into an internal buffer, while
|
||||
* remembering which of these types was used to place this copy.
|
||||
* The value can be later on extracted using a visitation like mechanism,
|
||||
* which takes a functor class and invokes a function \c access(T&) with
|
||||
* the type matching the current value in storage
|
||||
*/
|
||||
template<typename TYPES>
|
||||
struct Holder
|
||||
{
|
||||
|
||||
enum { TYPECNT = count<TYPES>::value
|
||||
, SIZE = maxSize<TYPES>::value
|
||||
};
|
||||
|
||||
|
||||
/** Storage to hold the actual value */
|
||||
struct Buffer
|
||||
{
|
||||
char buffer_[SIZE];
|
||||
uint which_;
|
||||
|
||||
Buffer() : which_(TYPECNT) {}
|
||||
|
||||
void*
|
||||
put (void)
|
||||
{
|
||||
deleteCurrent();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
deleteCurrent (); // depends on the Deleter, see below
|
||||
};
|
||||
|
||||
template<typename T, class BASE, uint idx>
|
||||
struct PlacementAdapter : BASE
|
||||
{
|
||||
T&
|
||||
put (T const& toStore)
|
||||
{
|
||||
BASE::deleteCurrent(); // remove old content, if any
|
||||
|
||||
T& storedObj = *new(BASE::buffer_) T (toStore);
|
||||
BASE::which_ = idx; // remember the actual type selected
|
||||
return storedObj;
|
||||
}
|
||||
|
||||
using BASE::put;
|
||||
};
|
||||
|
||||
typedef InstantiateWithIndex< TYPES
|
||||
, PlacementAdapter
|
||||
, Buffer
|
||||
>
|
||||
Storage;
|
||||
|
||||
|
||||
|
||||
/** provide a dispatcher table based visitation mechanism */
|
||||
template<class FUNCTOR>
|
||||
struct CaseSelect
|
||||
{
|
||||
typedef typename FUNCTOR::Ret Ret;
|
||||
typedef Ret (*Func)(Buffer&);
|
||||
|
||||
Func table_[TYPECNT];
|
||||
|
||||
CaseSelect ()
|
||||
{
|
||||
for (uint i=0; i<TYPECNT; ++i)
|
||||
table_[i] = 0;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static Ret
|
||||
trampoline (Buffer& storage)
|
||||
{
|
||||
T& content = reinterpret_cast<T&> (storage.buffer_);
|
||||
return FUNCTOR::access (content);
|
||||
}
|
||||
|
||||
Ret
|
||||
invoke (Buffer& storage)
|
||||
{
|
||||
if (TYPECNT <= storage.which_)
|
||||
return FUNCTOR::ifEmpty ();
|
||||
else
|
||||
return (*table_[storage.which_]) (storage);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template< class T, class BASE, uint i >
|
||||
struct CasePrepare
|
||||
: BASE
|
||||
{
|
||||
CasePrepare () : BASE()
|
||||
{
|
||||
BASE::table_[i] = &BASE::template trampoline<T>;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<class FUNCTOR>
|
||||
static typename FUNCTOR::Ret
|
||||
access (Buffer& buf)
|
||||
{
|
||||
typedef InstantiateWithIndex< TYPES
|
||||
, CasePrepare
|
||||
, CaseSelect<FUNCTOR>
|
||||
>
|
||||
Accessor;
|
||||
static Accessor select_case;
|
||||
return select_case.invoke(buf);
|
||||
}
|
||||
|
||||
|
||||
struct Deleter
|
||||
{
|
||||
typedef void Ret;
|
||||
|
||||
template<typename T>
|
||||
static void access (T& elem) { elem.~T(); }
|
||||
|
||||
static void ifEmpty () { }
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
template<typename TYPES>
|
||||
inline void
|
||||
Holder<TYPES>::Buffer::deleteCurrent ()
|
||||
{
|
||||
access<Deleter>(*this); // remove old content, if any
|
||||
which_ = TYPECNT; // mark as empty
|
||||
}
|
||||
|
||||
} // namespace variant
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* A variant wrapper (typesafe union) capable of holding a value of any
|
||||
* of a bounded collection of types. The value is stored in a local buffer
|
||||
* directly within the object and may be accessed by a typesafe visitation.
|
||||
*
|
||||
* \par
|
||||
* This utility class is similar to boost::variant and indeed was implemented
|
||||
* (5/08) in an effort to replace the latter in a draft solution for the problem
|
||||
* of typesafe access to the correct wrapper class from within some builder tool.
|
||||
* Well -- after finisihng this "exercise" I must admit that it is not really
|
||||
* much more simple than what boost::variant does internally. At least we are
|
||||
* pulling in fewer headers and the actual code path is shorter compared with
|
||||
* boost::variant, at the price of beeing not so generic, not caring for
|
||||
* alignment issues within the buffer and being <b>not threadsafe</b>
|
||||
*
|
||||
* @param TYPES collection of possible types to be stored in this variant object
|
||||
* @param Access policy how to access the stored value
|
||||
*/
|
||||
template< typename TYPES
|
||||
, template<typename> class Access
|
||||
>
|
||||
class Variant
|
||||
: boost::noncopyable
|
||||
{
|
||||
|
||||
typedef variant::Holder<TYPES> Holder;
|
||||
typedef typename Holder::Deleter Deleter;
|
||||
|
||||
|
||||
/** storage: buffer holding either and "empty" marker,
|
||||
* or one of the configured pointer to wrapper types */
|
||||
typename Holder::Storage holder_;
|
||||
|
||||
|
||||
public:
|
||||
void reset () { holder_.deleteCurrent();}
|
||||
|
||||
/** store a copy of the given argument within the
|
||||
* variant holder buffer, thereby typically casting
|
||||
* or converting the given source type to the best
|
||||
* suited (base) type (out of the collection of possible
|
||||
* types for this Variant instance)
|
||||
*/
|
||||
template<typename SRC>
|
||||
Variant&
|
||||
operator= (SRC src)
|
||||
{
|
||||
if (src) holder_.put (src); // see Holder::PlacementAdaptor::put
|
||||
else reset();
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** retrieve current content of the variant,
|
||||
* trying to cast or convert it to the given type.
|
||||
* Actually, the function \c access(T&) on the
|
||||
* Access-policy (template param) is invoked with the
|
||||
* type currently stored in the holder buffer.
|
||||
* May return NULL if conversion fails.
|
||||
*/
|
||||
template<typename TAR>
|
||||
TAR
|
||||
get ()
|
||||
{
|
||||
typedef Access<TAR> Extractor;
|
||||
return Holder::template access<Extractor> (this->holder_);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace lumiera
|
||||
#endif
|
||||
|
|
@ -105,7 +105,7 @@ namespace lumiera
|
|||
typedef RET ReturnType; ///< Tool function invocation return type
|
||||
typedef Tool ToolBase; ///< for templating the Tag and Dispatcher
|
||||
|
||||
virtual ~Tool () { }; ///< use RTTI for all visiting tools
|
||||
virtual ~Tool () { }; ///< use RTTI for all visiting tools
|
||||
|
||||
/** allows discovery of the concrete Tool type when dispatching a
|
||||
* visitor call. Can be implemented by inheriting from ToolTag */
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@
|
|||
|
||||
/** @file visitorpolicies.hpp
|
||||
** Policies usable for configuring the lumiera::visitor::Tool for different kinds of error handling.
|
||||
** @see buildertool.hpp for another flavor (calling and catch-all-function)
|
||||
** @see buildertool.hpp for another flavour (calling an catch-all-function there)
|
||||
**
|
||||
*/
|
||||
|
||||
|
|
|
|||
63
src/common/wrapperptr.hpp
Normal file
63
src/common/wrapperptr.hpp
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
WRAPPERPTR.hpp - variant record able to hold a pointer to some smart-ptr/wrapper types, providing conversions
|
||||
|
||||
Copyright (C) Lumiera.org
|
||||
2008, 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.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef LUMIERA_WRAPPERPTR_H
|
||||
#define LUMIERA_WRAPPERPTR_H
|
||||
|
||||
|
||||
#include "common/variant.hpp"
|
||||
#include "common/accesscasted.hpp"
|
||||
|
||||
#include "common/typelist.hpp"
|
||||
#include "proc/mobject/placement.hpp"
|
||||
#include "common/p.hpp"
|
||||
|
||||
|
||||
namespace asset { class Asset; }
|
||||
namespace mobject { class MObject; }
|
||||
|
||||
namespace lumiera {
|
||||
|
||||
|
||||
typedef typelist::Types < mobject::Placement<mobject::MObject>*
|
||||
, P<asset::Asset>*
|
||||
> ::List
|
||||
WrapperTypes;
|
||||
|
||||
/**
|
||||
* helper to treat various sorts of smart-ptrs uniformly.
|
||||
* Implemented as a variant-type value object, it is preconfigured
|
||||
* with the possible hierarchy-base classes used within this application.
|
||||
* Thus, when passing in an arbitrary smart-ptr, the best fitting smart-ptr
|
||||
* type pointing to the corresponding base class is selected for internal storage.
|
||||
* Later on, stored values can be retrieved either utilitzing static or dynamic casts;
|
||||
* error reporting is similar to the bahaviour of dynamic_cast<T>: when retrieving
|
||||
* a pointer, in case of mismatch NULL is returned.
|
||||
*/
|
||||
typedef lumiera::Variant<WrapperTypes, util::AccessCasted> WrapperPtr;
|
||||
|
||||
|
||||
|
||||
} // namespace lumiera
|
||||
#endif
|
||||
|
|
@ -41,12 +41,13 @@ using std::string;
|
|||
|
||||
namespace asset
|
||||
{
|
||||
using lumiera::P;
|
||||
|
||||
class Proc;
|
||||
class ProcPatt;
|
||||
|
||||
typedef shared_ptr<const asset::Proc> PProc;
|
||||
typedef shared_ptr<const asset::ProcPatt> PProcPatt;
|
||||
typedef P<const asset::Proc> PProc;
|
||||
typedef P<const asset::ProcPatt> PProcPatt;
|
||||
|
||||
|
||||
static Symbol CURRENT = "current";
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ namespace asset
|
|||
|
||||
};
|
||||
|
||||
typedef shared_ptr<const asset::Clip> PClipAsset;
|
||||
typedef P<const asset::Clip> PClipAsset;
|
||||
|
||||
const string CLIP_SUBFOLDER = "clips"; // TODO: handling of hard-wired constants....
|
||||
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ namespace asset
|
|||
bool del (ID<Asset> hash) { return table.erase (hash); }
|
||||
|
||||
template<class KIND>
|
||||
shared_ptr<KIND>
|
||||
P<KIND>
|
||||
get (ID<KIND> hash) const
|
||||
{
|
||||
return dynamic_pointer_cast<KIND,Asset> (find (hash));
|
||||
|
|
|
|||
|
|
@ -219,7 +219,7 @@ namespace asset
|
|||
* @throw Invalid if the given media asset is not top-level,
|
||||
* but rather part or a multichannel (compound) media
|
||||
*/
|
||||
shared_ptr<asset::Clip>
|
||||
P<asset::Clip>
|
||||
MediaFactory::operator() (asset::Media& mediaref) throw(lumiera::error::Invalid)
|
||||
{
|
||||
if (mediaref.checkCompound())
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ namespace asset
|
|||
class MediaFactory;
|
||||
class ProcPatt;
|
||||
|
||||
using lumiera::P;
|
||||
using lumiera::Time;
|
||||
|
||||
|
||||
|
|
@ -74,9 +75,9 @@ namespace asset
|
|||
const Time len_;
|
||||
|
||||
public:
|
||||
typedef shared_ptr<Media> PMedia;
|
||||
typedef shared_ptr<asset::Clip> PClip;
|
||||
typedef shared_ptr<asset::ProcPatt> PProcPatt;
|
||||
typedef P<Media> PMedia;
|
||||
typedef P<asset::Clip> PClip;
|
||||
typedef P<asset::ProcPatt> PProcPatt;
|
||||
typedef mobject::session::PClipMO PClipMO;
|
||||
|
||||
|
||||
|
|
@ -142,7 +143,7 @@ namespace asset
|
|||
class MediaFactory : public lumiera::Factory<asset::Media>
|
||||
{
|
||||
public:
|
||||
typedef shared_ptr<asset::Media> PType;
|
||||
typedef P<asset::Media> PType;
|
||||
|
||||
PType operator() (Asset::Ident& key, const string& file="");
|
||||
PType operator() (const string& file, const Category& cat);
|
||||
|
|
@ -152,7 +153,7 @@ namespace asset
|
|||
PType operator() (const char* file, const Category& cat);
|
||||
PType operator() (const char* file, asset::Kind);
|
||||
|
||||
shared_ptr<asset::Clip>
|
||||
P<asset::Clip>
|
||||
operator() (asset::Media& mediaref) throw(lumiera::error::Invalid);
|
||||
|
||||
};
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ namespace asset
|
|||
class MetaFactory : public lumiera::Factory<asset::Meta>
|
||||
{
|
||||
public:
|
||||
typedef shared_ptr<asset::Meta> PType;
|
||||
typedef P<asset::Meta> PType;
|
||||
|
||||
PType operator() (Asset::Ident& key); ////////////TODO define actual operation
|
||||
|
||||
|
|
|
|||
|
|
@ -31,9 +31,10 @@
|
|||
|
||||
namespace asset
|
||||
{
|
||||
using lumiera::P;
|
||||
|
||||
class Pipe;
|
||||
typedef shared_ptr<Pipe> PPipe;
|
||||
typedef P<Pipe> PPipe;
|
||||
|
||||
|
||||
template<>
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ namespace asset
|
|||
class Proc;
|
||||
class ProcFactory;
|
||||
|
||||
typedef shared_ptr<const Proc> PProc;
|
||||
typedef P<const Proc> PProc;
|
||||
|
||||
|
||||
|
||||
|
|
@ -97,7 +97,7 @@ namespace asset
|
|||
class ProcFactory : public lumiera::Factory<asset::Proc>
|
||||
{
|
||||
public:
|
||||
typedef shared_ptr<asset::Proc> PType;
|
||||
typedef P<asset::Proc> PType;
|
||||
|
||||
PType operator() (Asset::Ident& key); ////////////TODO define actual operation
|
||||
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ namespace asset
|
|||
* some ProcPatt as a template for creating more
|
||||
* spezialized patterns.
|
||||
*/
|
||||
shared_ptr<ProcPatt>
|
||||
P<ProcPatt>
|
||||
ProcPatt::newCopy (string newID) const
|
||||
{
|
||||
TODO ("implement the Pattern-ID within the propDescriptor!");
|
||||
|
|
|
|||
|
|
@ -35,13 +35,14 @@ using std::vector;
|
|||
|
||||
namespace asset
|
||||
{
|
||||
using lumiera::P;
|
||||
using lumiera::Symbol;
|
||||
|
||||
class Proc;
|
||||
class ProcPatt;
|
||||
class BuildInstruct;
|
||||
typedef shared_ptr<const asset::Proc> PProc;
|
||||
typedef shared_ptr<const asset::ProcPatt> PProcPatt;
|
||||
typedef P<const asset::Proc> PProc;
|
||||
typedef P<const asset::ProcPatt> PProcPatt;
|
||||
|
||||
typedef vector<BuildInstruct> InstructionSequence;
|
||||
|
||||
|
|
@ -61,14 +62,13 @@ namespace asset
|
|||
friend class StructFactoryImpl;
|
||||
|
||||
public:
|
||||
shared_ptr<ProcPatt> newCopy (string newID) const;
|
||||
P<ProcPatt> newCopy (string newID) const;
|
||||
|
||||
ProcPatt& attach (Symbol where, PProc& node);
|
||||
ProcPatt& operator+= (PProcPatt& toReuse);
|
||||
|
||||
};
|
||||
|
||||
typedef shared_ptr<const asset::ProcPatt> PProcPatt;
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -89,10 +89,10 @@ namespace asset
|
|||
* created as a side effect of calling the concrete Struct subclass ctor.
|
||||
*/
|
||||
template<class STRU>
|
||||
shared_ptr<STRU>
|
||||
P<STRU>
|
||||
StructFactory::operator() (const Query<STRU>& capabilities)
|
||||
{
|
||||
shared_ptr<STRU> res;
|
||||
P<STRU> res;
|
||||
QueryHandler<STRU>& typeHandler = ConfigRules::instance();
|
||||
typeHandler.resolve (res, capabilities);
|
||||
|
||||
|
|
@ -117,7 +117,7 @@ namespace asset
|
|||
* @see ProcPatt
|
||||
* @see DefaultsManager
|
||||
*/
|
||||
shared_ptr<Pipe>
|
||||
P<Pipe>
|
||||
StructFactory::operator() (string pipeID, string streamID)
|
||||
{
|
||||
normalizeID (pipeID);
|
||||
|
|
@ -147,9 +147,9 @@ namespace asset
|
|||
namespace asset
|
||||
{
|
||||
|
||||
template shared_ptr<Pipe> StructFactory::operator() (const Query<Pipe>& query);
|
||||
template shared_ptr<Track> StructFactory::operator() (const Query<Track>& query);
|
||||
template PProcPatt StructFactory::operator() (const Query<const ProcPatt>& query);
|
||||
template P<Pipe> StructFactory::operator() (const Query<Pipe>& query);
|
||||
template P<Track> StructFactory::operator() (const Query<Track>& query);
|
||||
template PProcPatt StructFactory::operator() (const Query<const ProcPatt>& query);
|
||||
|
||||
|
||||
} // namespace asset
|
||||
|
|
|
|||
|
|
@ -120,12 +120,12 @@ namespace asset
|
|||
|
||||
|
||||
public:
|
||||
typedef shared_ptr<asset::Struct> PType;
|
||||
typedef P<asset::Struct> PType;
|
||||
|
||||
template<class STRU>
|
||||
shared_ptr<STRU> operator() (const Query<STRU>& query); ////////////TODO actually do something sensible here
|
||||
P<STRU> operator() (const Query<STRU>& query); ////////////TODO actually do something sensible here
|
||||
|
||||
shared_ptr<Pipe> operator() (string pipeID, string streamID);
|
||||
P<Pipe> operator() (string pipeID, string streamID);
|
||||
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ namespace asset
|
|||
};
|
||||
|
||||
|
||||
typedef shared_ptr<const Track> PTrack;
|
||||
typedef P<const Track> PTrack;
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -130,11 +130,11 @@ namespace asset
|
|||
* of the stored object differs and can't be casted.
|
||||
*/
|
||||
template<class KIND>
|
||||
shared_ptr<KIND>
|
||||
P<KIND>
|
||||
AssetManager::getAsset (const ID<KIND>& id)
|
||||
throw(lumiera::error::Invalid)
|
||||
{
|
||||
if (shared_ptr<KIND> obj = registry.get (id))
|
||||
if (P<KIND> obj = registry.get (id))
|
||||
return obj;
|
||||
else
|
||||
if (known (id)) // provide Ident tuple of existing Asset
|
||||
|
|
@ -143,14 +143,14 @@ namespace asset
|
|||
throw UnknownID (id);
|
||||
}
|
||||
|
||||
/** convienience shortcut for fetching the registered shared_ptr
|
||||
/** convienience shortcut for fetching the registered smart-ptr
|
||||
* which is in charge of the given asset instance. By querying
|
||||
* directly asset.id (of type ID<Asset>), the call to registry.get()
|
||||
* can bypass the dynamic cast, because the type of the asset
|
||||
* is explicitely given by type KIND.
|
||||
*/
|
||||
template<class KIND>
|
||||
shared_ptr<KIND>
|
||||
P<KIND>
|
||||
AssetManager::wrap (const KIND& asset)
|
||||
{
|
||||
ENSURE (instance().known(asset.id),
|
||||
|
|
@ -169,7 +169,7 @@ namespace asset
|
|||
{
|
||||
return ( registry.get (ID<Asset>(id)) );
|
||||
} // query most general Asset ID-kind and use implicit
|
||||
// conversion from shared_ptr to bool (test if empty)
|
||||
// conversion from smart-ptr to bool (test if empty)
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -245,18 +245,18 @@ namespace asset
|
|||
template ID<Asset> AssetManager::reg (Asset* obj, const Asset::Ident& idi);
|
||||
|
||||
|
||||
template shared_ptr<Asset> AssetManager::getAsset (const ID<Asset>& id) throw(lumiera::error::Invalid);
|
||||
template shared_ptr<Media> AssetManager::getAsset (const ID<Media>& id) throw(lumiera::error::Invalid);
|
||||
template shared_ptr<Proc> AssetManager::getAsset (const ID<Proc>& id) throw(lumiera::error::Invalid);
|
||||
template shared_ptr<Struct> AssetManager::getAsset (const ID<Struct>& id) throw(lumiera::error::Invalid);
|
||||
template shared_ptr<Meta> AssetManager::getAsset (const ID<Meta>& id) throw(lumiera::error::Invalid);
|
||||
template P<Asset> AssetManager::getAsset (const ID<Asset>& id) throw(lumiera::error::Invalid);
|
||||
template P<Media> AssetManager::getAsset (const ID<Media>& id) throw(lumiera::error::Invalid);
|
||||
template P<Proc> AssetManager::getAsset (const ID<Proc>& id) throw(lumiera::error::Invalid);
|
||||
template P<Struct> AssetManager::getAsset (const ID<Struct>& id) throw(lumiera::error::Invalid);
|
||||
template P<Meta> AssetManager::getAsset (const ID<Meta>& id) throw(lumiera::error::Invalid);
|
||||
|
||||
template shared_ptr<Asset> AssetManager::wrap (const Asset& asset);
|
||||
template shared_ptr<Media> AssetManager::wrap (const Media& asset);
|
||||
template shared_ptr<Clip> AssetManager::wrap (const Clip& asset);
|
||||
template shared_ptr<Track> AssetManager::wrap (const Track& asset);
|
||||
template shared_ptr<Pipe> AssetManager::wrap (const Pipe& asset);
|
||||
template shared_ptr<ProcPatt> AssetManager::wrap (const ProcPatt& asset);
|
||||
template P<Asset> AssetManager::wrap (const Asset& asset);
|
||||
template P<Media> AssetManager::wrap (const Media& asset);
|
||||
template P<Clip> AssetManager::wrap (const Clip& asset);
|
||||
template P<Track> AssetManager::wrap (const Track& asset);
|
||||
template P<Pipe> AssetManager::wrap (const Pipe& asset);
|
||||
template P<ProcPatt> AssetManager::wrap (const ProcPatt& asset);
|
||||
|
||||
|
||||
} // namespace asset
|
||||
|
|
|
|||
|
|
@ -73,13 +73,13 @@ namespace asset
|
|||
/** provide the unique ID for given Asset::Ident tuple */
|
||||
static ID<Asset> getID (const Asset::Ident&);
|
||||
|
||||
/** retrieve the registerd shared_ptr for any asset */
|
||||
/** retrieve the registerd smart-ptr for any asset */
|
||||
template<class KIND>
|
||||
static shared_ptr<KIND> wrap (const KIND& asset);
|
||||
static P<KIND> wrap (const KIND& asset);
|
||||
|
||||
/** find and return corresponging object */
|
||||
template<class KIND>
|
||||
shared_ptr<KIND> getAsset (const ID<KIND>& id) throw(lumiera::error::Invalid);
|
||||
P<KIND> getAsset (const ID<KIND>& id) throw(lumiera::error::Invalid);
|
||||
|
||||
|
||||
/** @return true if the given id is registered in the internal asset DB */
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
|
||||
/* common types frequently used... */
|
||||
|
||||
#include "common/p.hpp"
|
||||
#include "common/util.hpp"
|
||||
#include "common/time.hpp"
|
||||
#include "common/error.hpp" ///< pulls in NoBug via nobugcfg.hpp
|
||||
|
|
|
|||
70
src/proc/mobject/builder/applicablebuildertargettypes.hpp
Normal file
70
src/proc/mobject/builder/applicablebuildertargettypes.hpp
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
ApplicableBuilderTargetTypes - definitinon header specifying all types treated by builder tools
|
||||
|
||||
Copyright (C) Lumiera.org
|
||||
2008, 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.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifndef MOBJECT_BUILDER_APPLICABLEBUILDERTARGETTYPES_H
|
||||
#define MOBJECT_BUILDER_APPLICABLEBUILDERTARGETTYPES_H
|
||||
|
||||
#include "proc/mobject/builder/buildertool.hpp"
|
||||
|
||||
|
||||
|
||||
namespace mobject {
|
||||
namespace session {
|
||||
|
||||
class Clip;
|
||||
class Effect;
|
||||
class AbstractMO;
|
||||
template<class VAL> class Auto;
|
||||
// Forward declarations sufficient here...
|
||||
// actual definitions necessary only in the
|
||||
// implementation file (*cpp) of the builder tool.
|
||||
}
|
||||
|
||||
namespace builder {
|
||||
|
||||
typedef Types< session::Clip,
|
||||
session::Effect,
|
||||
session::AbstractMO
|
||||
> ::List
|
||||
BuilderTargetTypes;
|
||||
|
||||
|
||||
/**
|
||||
* Marker used to declare some visiting Tool class to be actually a
|
||||
* mobject::builder::BuilderTool and to possibly accept and treat the
|
||||
* common selection of types to be handled by any such builder tool.
|
||||
* The actual BuilderTool impl should inherit from this template by
|
||||
* feeding back its type (CRTP), this causes a dispatcher table entry
|
||||
* be generated for this concrete BuilderTool implementation.
|
||||
*/
|
||||
template<class TOOL>
|
||||
struct ApplicableBuilderTargetTypes
|
||||
: Applicable<TOOL, BuilderTargetTypes>
|
||||
{ };
|
||||
|
||||
|
||||
|
||||
} // namespace mobject::builder
|
||||
|
||||
} // namespace mobject
|
||||
#endif
|
||||
|
|
@ -20,20 +20,54 @@
|
|||
|
||||
*/
|
||||
|
||||
/** @file buildertool.hpp
|
||||
** Visiting-tool mechanism configured specifically for the Builder.
|
||||
** The Builder creates the render nodes network by applying several Builder Tools
|
||||
** to the objects found in the Session, EDL and Fixture. These BuilderTool instances
|
||||
** contain the details of the builder implementation.
|
||||
**
|
||||
** As the objects to be treated are normally handled by smart-ptrs, BuilderTool provides
|
||||
** a special facility for dealing with these wrapped objects. There are some liabilities.
|
||||
** <ul><li>each concrete Buildable subtype to be treated specifically needs to
|
||||
** declare \c DEFINE_PROCESSABLE_BY(BuilderTool) </li>
|
||||
** <li>at the same time, the concrete BuilderTool subclass has to declare
|
||||
** being Applicable to this concrete Buildable subtype. The recommended way
|
||||
** of ensuring this, is to add an entry to applicablebuildertargettypes.hpp
|
||||
** and then derive the concrete BuilderTool subclass from
|
||||
** ApplicableBuilderTargetTypes</li>
|
||||
** <li>when accessing the wrapper from within a \c treat() function, a suitable
|
||||
** concrete wrapper type has to be specified. If the wrapper type used for
|
||||
** invoking the BuilderTool (function \c apply(BuilderTool&l, WrappedObject&) )
|
||||
** can not be converted to this type requested from within the call, an
|
||||
** assertion failure (or segmentation fault in a release build) will result.</li>
|
||||
** </ul>
|
||||
**
|
||||
** @see visitor.hpp
|
||||
** @see applicablebuildertargettypes.hpp
|
||||
** @see buildertooltest.hpp
|
||||
** @see nodecreatertool.hpp
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef MOBJECT_BUILDER_TOOL_H
|
||||
#define MOBJECT_BUILDER_TOOL_H
|
||||
|
||||
#include "common/visitor.hpp"
|
||||
#include "common/wrapperptr.hpp"
|
||||
|
||||
#include "common/p.hpp"
|
||||
#include "proc/mobject/placement.hpp"
|
||||
#include "proc/mobject/explicitplacement.hpp"
|
||||
|
||||
|
||||
namespace mobject {
|
||||
|
||||
namespace mobject
|
||||
{
|
||||
class Buildable;
|
||||
|
||||
namespace builder
|
||||
{
|
||||
namespace builder {
|
||||
|
||||
using lumiera::P;
|
||||
|
||||
/**
|
||||
* Policy invoking an catch-all function for processing
|
||||
|
|
@ -49,19 +83,79 @@ namespace mobject
|
|||
virtual RET onUnknown (Buildable& target) = 0;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Base class of all BuilderTools, used according to the visitor pattern:
|
||||
* each Tool contains the concrete implementation for one task to be done
|
||||
* to the various MObject classes. The concrete builder tool implementation
|
||||
* should not diretcly inherit from this base interface, but rather through
|
||||
* an instantiation of the "Applicable" template parametrized with all
|
||||
* concrete Buildable classes, for which it wants calls to be dispatched.
|
||||
* concrete Buildable classes, for which it wants calls to be dispatched.
|
||||
* \par
|
||||
* In addition to lumiera::visitor::Tool, BuilderTool adds support for dealing
|
||||
* with objects normally handled by means of smart-pointers or similar
|
||||
* wrappers, most notably mobject::Placement. The visitaion is initiated
|
||||
* by calling the stand-alone function \c (BuilderTool& tool, WRA& wrappedTargetObj) ,
|
||||
* which forwards to the visitation mechanism supported by the type contained
|
||||
* in the wrapper, but stores away a pointer to the wrapped object, which can
|
||||
* be retrieved in a typesafe manner from within the \c treat(ConcreteType&)
|
||||
* function.
|
||||
* @note retrieving the wrapper is <b>not threadsafe</b> and <b>not reentrant</b>,
|
||||
* as we simply store a pointer within the BuilderTool instance.
|
||||
*/
|
||||
typedef lumiera::visitor::Tool<void, InvokeCatchAllFunction> BuilderTool;
|
||||
class BuilderTool
|
||||
: public lumiera::visitor::Tool<void, InvokeCatchAllFunction>
|
||||
{
|
||||
lumiera::WrapperPtr currentWrapper_;
|
||||
|
||||
public:
|
||||
|
||||
template<template<class> class WRA, class TAR>
|
||||
void rememberWrapper (WRA<TAR>* ptr_toWrappedTarget)
|
||||
{
|
||||
currentWrapper_ = ptr_toWrappedTarget;
|
||||
}
|
||||
|
||||
void forgetWrapper ()
|
||||
{
|
||||
currentWrapper_.reset();
|
||||
}
|
||||
|
||||
|
||||
protected: /* == interface for accessing the wrapper from within tool application == */
|
||||
|
||||
template<class TAR>
|
||||
Placement<TAR>&
|
||||
getPlacement ()
|
||||
{
|
||||
Placement<TAR>* pPlacement = currentWrapper_.get<Placement<TAR>*>();
|
||||
ENSURE (pPlacement, "wrong target type when invoking %s", __PRETTY_FUNCTION__);
|
||||
return *pPlacement;
|
||||
}
|
||||
|
||||
ExplicitPlacement
|
||||
getExplicitPlacement ()
|
||||
{
|
||||
return getPlacement<MObject>().resolve();
|
||||
}
|
||||
|
||||
template<class TAR>
|
||||
lumiera::P<TAR>
|
||||
getPtr ()
|
||||
{
|
||||
P<TAR>* pP = currentWrapper_.get<P<TAR>*>();
|
||||
ENSURE (pP, "wrong target type when invoking %s", __PRETTY_FUNCTION__);
|
||||
return *pP;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* declare the concrete types a BuilderTool may recievee and treat.
|
||||
* @note it is recommended to use ApplicableBuilderTargetTypes
|
||||
*/
|
||||
template
|
||||
< class TOOLImpl, // concrete BuilderTool implementation
|
||||
class TYPELIST // list of all concrete Buildables to be treated
|
||||
|
|
@ -71,17 +165,33 @@ namespace mobject
|
|||
{ }
|
||||
;
|
||||
|
||||
using lumiera::typelist::Types; // convienience for the users of "Applicable"
|
||||
|
||||
using lumiera::typelist::Types; // convenience for the users of "Applicable"
|
||||
|
||||
} // namespace mobject::builder
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Marker Interface for classes Visitable by Builder tools.
|
||||
* Marker Interface for classes visitable by Builder tools.
|
||||
*/
|
||||
class Buildable : public lumiera::visitor::Visitable<builder::BuilderTool>
|
||||
{ };
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
namespace builder { // to be found by ADL
|
||||
|
||||
template<typename WRA>
|
||||
inline Buildable::ReturnType
|
||||
apply (BuilderTool& tool, WRA& wrappedTargetObj)
|
||||
{
|
||||
tool.rememberWrapper(&wrappedTargetObj);
|
||||
wrappedTargetObj->apply (tool); // dispatch to suitable treat() function
|
||||
tool.forgetWrapper();
|
||||
}
|
||||
|
||||
} // namespace mobject::builder
|
||||
|
||||
} // namespace mobject
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -31,11 +31,8 @@ using mobject::session::Clip;
|
|||
using mobject::session::Effect;
|
||||
using mobject::session::Auto;
|
||||
|
||||
namespace mobject
|
||||
{
|
||||
|
||||
namespace builder
|
||||
{
|
||||
namespace mobject {
|
||||
namespace builder {
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -24,23 +24,15 @@
|
|||
#ifndef MOBJECT_BUILDER_NODECREATERTOOL_H
|
||||
#define MOBJECT_BUILDER_NODECREATERTOOL_H
|
||||
|
||||
#include "proc/mobject/builder/buildertool.hpp"
|
||||
|
||||
#include "proc/mobject/builder/applicablebuildertargettypes.hpp"
|
||||
|
||||
#include "proc/engine/processor.hpp"
|
||||
|
||||
|
||||
|
||||
namespace mobject
|
||||
{
|
||||
namespace session
|
||||
{
|
||||
// Forward declarations
|
||||
class Effect;
|
||||
class Clip;
|
||||
template<class VAL> class Auto;
|
||||
}
|
||||
|
||||
namespace builder
|
||||
{
|
||||
namespace mobject {
|
||||
namespace builder {
|
||||
|
||||
|
||||
|
||||
|
|
@ -52,11 +44,10 @@ namespace mobject
|
|||
* render engine under construction such as to reflect the properties
|
||||
* of the MObject in the actual render.
|
||||
*/
|
||||
class NodeCreatorTool : public BuilderTool
|
||||
class NodeCreatorTool
|
||||
: public ApplicableBuilderTargetTypes<NodeCreatorTool>
|
||||
{
|
||||
|
||||
//////////////////////////////////////////////TODO: switch to acyclic visitior!!!!!!!!!!!!!
|
||||
|
||||
public:
|
||||
virtual void treat (mobject::session::Clip& clip) ;
|
||||
virtual void treat (mobject::session::Effect& effect) ;
|
||||
|
|
|
|||
|
|
@ -31,10 +31,8 @@ using mobject::session::Clip;
|
|||
using mobject::session::Effect;
|
||||
|
||||
|
||||
namespace mobject
|
||||
{
|
||||
namespace builder
|
||||
{
|
||||
namespace mobject {
|
||||
namespace builder {
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -24,26 +24,18 @@
|
|||
#ifndef MOBJECT_BUILDER_SEGMENTATIONTOOL_H
|
||||
#define MOBJECT_BUILDER_SEGMENTATIONTOOL_H
|
||||
|
||||
#include <list>
|
||||
|
||||
#include "proc/mobject/builder/buildertool.hpp"
|
||||
#include "proc/mobject/builder/applicablebuildertargettypes.hpp"
|
||||
|
||||
#include "proc/mobject/session/segment.hpp"
|
||||
|
||||
#include <list>
|
||||
using std::list;
|
||||
|
||||
|
||||
|
||||
namespace mobject
|
||||
{
|
||||
namespace session
|
||||
{
|
||||
// Forward declarations
|
||||
class Clip;
|
||||
class Effect;
|
||||
}
|
||||
|
||||
namespace builder
|
||||
{
|
||||
namespace mobject {
|
||||
namespace builder {
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -53,10 +45,10 @@ namespace mobject
|
|||
* can be represented by automation solely, without the need
|
||||
* to change the node connections.
|
||||
*/
|
||||
class SegmentationTool : public BuilderTool
|
||||
class SegmentationTool
|
||||
: public ApplicableBuilderTargetTypes<SegmentationTool>
|
||||
{
|
||||
|
||||
//////////////////////////////////////////////TODO: switch to acyclic visitior!!!!!!!!!!!!!
|
||||
|
||||
public:
|
||||
void treat (mobject::session::Clip& clip) ;
|
||||
|
|
|
|||
|
|
@ -30,9 +30,9 @@
|
|||
|
||||
namespace mobject
|
||||
{
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Special kind of Placement, where the location of the
|
||||
* MObject has been nailed down to a fixed position.
|
||||
|
|
@ -51,7 +51,7 @@ namespace mobject
|
|||
const Pipe pipe;
|
||||
|
||||
typedef std::pair<Time,Pipe> SolutionData; //TODO (ichthyo consideres better passing of solution by subclass)
|
||||
|
||||
|
||||
/** no need to resolve any further, as this ExplicitPlacement
|
||||
* already \e is the result of a resolve()-call.
|
||||
*/
|
||||
|
|
@ -60,7 +60,8 @@ namespace mobject
|
|||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected:
|
||||
/* @todo ichthyo considers a much more elegant implementation utilizing a subclass
|
||||
* of FixedLocation, which would serve as Placement::LocatingSolution, and
|
||||
|
|
@ -79,8 +80,8 @@ namespace mobject
|
|||
/** copying prohibited, ExplicitPlacement is effectively const! */
|
||||
ExplicitPlacement& operator= (const ExplicitPlacement&);
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace mobject
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -26,17 +26,18 @@
|
|||
|
||||
#include "pre.hpp"
|
||||
|
||||
#include <list>
|
||||
#include <tr1/memory>
|
||||
|
||||
#include "proc/lumiera.hpp"
|
||||
#include "proc/mobject/builder/buildertool.hpp"
|
||||
#include "proc/mobject/placement.hpp"
|
||||
#include "proc/asset.hpp" // TODO finally not needed?
|
||||
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <boost/operators.hpp>
|
||||
#include <list>
|
||||
|
||||
|
||||
using std::list;
|
||||
using std::tr1::shared_ptr;
|
||||
|
||||
#include "proc/assetmanager.hpp"
|
||||
using proc_interface::IDA; // TODO finally not needed?
|
||||
|
|
@ -45,6 +46,7 @@ using proc_interface::AssetManager;
|
|||
|
||||
namespace mobject
|
||||
{
|
||||
using lumiera::P;
|
||||
|
||||
namespace session
|
||||
{
|
||||
|
|
@ -58,7 +60,10 @@ namespace mobject
|
|||
* manipulated and finally rendered within Lumiera's EDL
|
||||
* are MObjects.
|
||||
*/
|
||||
class MObject : public Buildable
|
||||
class MObject
|
||||
: public Buildable,
|
||||
boost::noncopyable,
|
||||
boost::equality_comparable< MObject >
|
||||
{
|
||||
protected:
|
||||
typedef lumiera::Time Time;
|
||||
|
|
@ -79,11 +84,14 @@ namespace mobject
|
|||
virtual bool isValid() const =0;
|
||||
|
||||
virtual Time& getLength() =0; ///< @todo how to deal with the time/length field??
|
||||
|
||||
virtual bool operator== (const MObject& oo) const =0;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
typedef Placement<MObject> PMO;
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -23,25 +23,39 @@
|
|||
|
||||
#include "proc/mobject/placement.hpp"
|
||||
#include "proc/mobject/explicitplacement.hpp"
|
||||
#include "proc/mobject/mobject.hpp"
|
||||
|
||||
#include <boost/format.hpp>
|
||||
using boost::str;
|
||||
|
||||
namespace mobject
|
||||
{
|
||||
|
||||
|
||||
/** @note we know we need only this single
|
||||
* specialisation, because we define
|
||||
* the Placements of more specific
|
||||
* MObject kinds to be subclasses
|
||||
* of Placement<MObject>, so they
|
||||
* will inherit this function.
|
||||
*/
|
||||
template<>
|
||||
template<class MO>
|
||||
ExplicitPlacement
|
||||
Placement<MObject>::resolve () const
|
||||
Placement<MO>::resolve () const
|
||||
{
|
||||
return ExplicitPlacement (*this, chain.resolve());
|
||||
}
|
||||
|
||||
/** @note we know we need only this single specialisation,
|
||||
* because we define the Placements of more specific
|
||||
* MObject kinds to be subclasses of Placement<MObject>,
|
||||
* so they will inherit this function.
|
||||
*/
|
||||
template ExplicitPlacement Placement<MObject>::resolve() const;
|
||||
|
||||
|
||||
|
||||
template<>
|
||||
Placement<MObject>::operator string () const
|
||||
{
|
||||
static boost::format fmt("Placement<%s> %|50T.| use-cnt=%x adr=%x pointee=%x");
|
||||
return str(fmt % typeid(*get()).name() % use_count() % this % get() );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace mobject
|
||||
|
|
|
|||
|
|
@ -58,12 +58,10 @@
|
|||
#define MOBJECT_PLACEMENT_H
|
||||
|
||||
#include "pre.hpp"
|
||||
#include "proc/mobject/mobject.hpp"
|
||||
#include "proc/mobject/session/locatingpin.hpp"
|
||||
#include "proc/asset/pipe.hpp"
|
||||
|
||||
#include <tr1/memory>
|
||||
using std::tr1::shared_ptr;
|
||||
|
||||
|
||||
namespace mobject
|
||||
|
|
@ -72,6 +70,7 @@ namespace mobject
|
|||
|
||||
class ExplicitPlacement;
|
||||
|
||||
using std::tr1::shared_ptr;
|
||||
|
||||
|
||||
|
||||
|
|
@ -85,6 +84,7 @@ namespace mobject
|
|||
class Placement : protected shared_ptr<MO>
|
||||
{
|
||||
protected:
|
||||
typedef shared_ptr<MO> Base;
|
||||
typedef lumiera::Time Time;
|
||||
typedef asset::shared_ptr<asset::Pipe> Pipe;
|
||||
|
||||
|
|
@ -99,13 +99,14 @@ namespace mobject
|
|||
operator-> () const
|
||||
{
|
||||
ENSURE (*this);
|
||||
return shared_ptr<MO>::operator-> ();
|
||||
return Base::operator-> ();
|
||||
}
|
||||
|
||||
operator string() const ;
|
||||
size_t use_count() const { return Base::use_count(); }
|
||||
|
||||
virtual ~Placement() {};
|
||||
|
||||
/** */ /////////////////////////////////////////////////////////////TODO: totmachen?
|
||||
// DEFINE_PROCESSABLE_BY (builder::BuilderTool);
|
||||
|
||||
|
||||
/** interface for defining the kind of placement
|
||||
|
|
@ -128,20 +129,19 @@ namespace mobject
|
|||
friend class session::MObjectFactory;
|
||||
};
|
||||
|
||||
typedef Placement<MObject> PMO;
|
||||
|
||||
|
||||
|
||||
|
||||
/* === defining specialisations to be subclasses === */
|
||||
|
||||
#define DEFINE_SPECIALIZED_PLACEMENT(SUBCLASS) \
|
||||
#define DEFINE_SPECIALIZED_PLACEMENT(SUBCLASS, BASE) \
|
||||
template<> \
|
||||
class Placement<SUBCLASS> : public Placement<MObject> \
|
||||
class Placement<SUBCLASS> : public Placement<BASE> \
|
||||
{ \
|
||||
protected: \
|
||||
Placement (SUBCLASS & m, void (*moKiller)(MObject*)) \
|
||||
: Placement<MObject>::Placement (m, moKiller) \
|
||||
: Placement<BASE>::Placement (m, moKiller) \
|
||||
{ }; \
|
||||
friend class session::MObjectFactory; \
|
||||
\
|
||||
|
|
@ -154,7 +154,6 @@ namespace mobject
|
|||
(shared_ptr<MObject>::operator-> ()); \
|
||||
} \
|
||||
};
|
||||
// DEFINE_PROCESSABLE_BY (builder::BuilderTool);
|
||||
|
||||
/* a note to the maintainer: please don't add any fields or methods to
|
||||
* these subclasses which aren't also present in Placement<MObject>!
|
||||
|
|
|
|||
|
|
@ -28,8 +28,14 @@ namespace mobject
|
|||
namespace session
|
||||
{
|
||||
|
||||
/** */
|
||||
|
||||
/** default/fallback implementation of equality
|
||||
* using literal object identity (same address)
|
||||
*/
|
||||
bool
|
||||
AbstractMO::operator== (const MObject& oo) const
|
||||
{
|
||||
return (this == &oo);
|
||||
}
|
||||
|
||||
|
||||
} // namespace mobject::session
|
||||
|
|
|
|||
|
|
@ -49,6 +49,8 @@ namespace mobject
|
|||
|
||||
DEFINE_PROCESSABLE_BY (builder::BuilderTool);
|
||||
|
||||
virtual bool operator== (const MObject& oo) const;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -38,8 +38,8 @@ namespace mobject
|
|||
namespace session
|
||||
{
|
||||
using asset::Media;
|
||||
typedef shared_ptr<Media> PMedia;
|
||||
typedef shared_ptr<asset::Clip> PClipAsset;
|
||||
typedef P<Media> PMedia;
|
||||
typedef P<asset::Clip> PClipAsset;
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -66,6 +66,7 @@ namespace mobject
|
|||
and the unlink() function of the asset should take it into
|
||||
account when breaking circular references.
|
||||
*/
|
||||
|
||||
const Media & mediaDef_;
|
||||
const asset::Clip & clipDef_;
|
||||
|
||||
|
|
@ -98,7 +99,7 @@ namespace mobject
|
|||
} // namespace mobject::session
|
||||
|
||||
/** Placement<Clip> defined to be subclass of Placement<MObject> */
|
||||
DEFINE_SPECIALIZED_PLACEMENT (session::Clip);
|
||||
DEFINE_SPECIALIZED_PLACEMENT (session::Clip, MObject);
|
||||
|
||||
|
||||
} // namespace mobject
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ namespace mobject
|
|||
{
|
||||
namespace session
|
||||
{
|
||||
using std::tr1::shared_ptr;
|
||||
using lumiera::P;
|
||||
|
||||
|
||||
|
||||
|
|
@ -52,10 +52,10 @@ namespace mobject
|
|||
|
||||
|
||||
template<class TAR>
|
||||
shared_ptr<TAR>
|
||||
P<TAR>
|
||||
DefsManager::search (const Query<TAR>& capabilities)
|
||||
{
|
||||
shared_ptr<TAR> res;
|
||||
P<TAR> res;
|
||||
QueryHandler<TAR>& typeHandler = ConfigRules::instance();
|
||||
for (DefsRegistry::Iter<TAR> i = defsRegistry->candidates(capabilities);
|
||||
res = *i ; ++i )
|
||||
|
|
@ -69,10 +69,10 @@ namespace mobject
|
|||
|
||||
|
||||
template<class TAR>
|
||||
shared_ptr<TAR>
|
||||
P<TAR>
|
||||
DefsManager::create (const Query<TAR>& capabilities)
|
||||
{
|
||||
shared_ptr<TAR> res;
|
||||
P<TAR> res;
|
||||
QueryHandler<TAR>& typeHandler = ConfigRules::instance();
|
||||
typeHandler.resolve (res, capabilities);
|
||||
if (res)
|
||||
|
|
@ -83,9 +83,9 @@ namespace mobject
|
|||
|
||||
template<class TAR>
|
||||
bool
|
||||
DefsManager::define (const shared_ptr<TAR>& defaultObj, const Query<TAR>& capabilities)
|
||||
DefsManager::define (const P<TAR>& defaultObj, const Query<TAR>& capabilities)
|
||||
{
|
||||
shared_ptr<TAR> candidate (defaultObj);
|
||||
P<TAR> candidate (defaultObj);
|
||||
QueryHandler<TAR>& typeHandler = ConfigRules::instance();
|
||||
typeHandler.resolve (candidate, capabilities);
|
||||
if (!candidate)
|
||||
|
|
@ -97,17 +97,17 @@ namespace mobject
|
|||
|
||||
template<class TAR>
|
||||
bool
|
||||
DefsManager::forget (const shared_ptr<TAR>& defaultObj)
|
||||
DefsManager::forget (const P<TAR>& defaultObj)
|
||||
{
|
||||
return defsRegistry->forget (defaultObj);
|
||||
}
|
||||
|
||||
|
||||
template<class TAR>
|
||||
shared_ptr<TAR>
|
||||
P<TAR>
|
||||
DefsManager::operator() (const Query<TAR>& capabilities)
|
||||
{
|
||||
shared_ptr<TAR> res (search (capabilities));
|
||||
P<TAR> res (search (capabilities));
|
||||
if (res)
|
||||
return res;
|
||||
else
|
||||
|
|
|
|||
|
|
@ -25,11 +25,11 @@
|
|||
#define MOBJECT_SESSION_DEFSMANAGER_H
|
||||
|
||||
|
||||
#include "common/p.hpp"
|
||||
#include "common/query.hpp"
|
||||
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
#include <boost/utility.hpp>
|
||||
#include <tr1/memory>
|
||||
|
||||
|
||||
|
||||
|
|
@ -37,7 +37,7 @@ namespace mobject
|
|||
{
|
||||
namespace session
|
||||
{
|
||||
using std::tr1::shared_ptr;
|
||||
using lumiera::P;
|
||||
using boost::scoped_ptr;
|
||||
|
||||
class DefsRegistry;
|
||||
|
|
@ -69,14 +69,14 @@ namespace mobject
|
|||
* is considered \e misconfiguration.
|
||||
*/
|
||||
template<class TAR>
|
||||
shared_ptr<TAR> operator() (const lumiera::Query<TAR>&);
|
||||
P<TAR> operator() (const lumiera::Query<TAR>&);
|
||||
|
||||
|
||||
/** search through the registered defaults, never create anything.
|
||||
* @return object fulfilling the query, \c empty ptr if not found.
|
||||
*/
|
||||
template<class TAR>
|
||||
shared_ptr<TAR> search (const lumiera::Query<TAR>&);
|
||||
P<TAR> search (const lumiera::Query<TAR>&);
|
||||
|
||||
/** retrieve an object fulfilling the query and register it as default.
|
||||
* The resolution is delegated to the ConfigQuery system (which may cause
|
||||
|
|
@ -84,7 +84,7 @@ namespace mobject
|
|||
* @return object fulfilling the query, \c empty ptr if no solution.
|
||||
*/
|
||||
template<class TAR>
|
||||
shared_ptr<TAR> create (const lumiera::Query<TAR>&);
|
||||
P<TAR> create (const lumiera::Query<TAR>&);
|
||||
|
||||
/** register the given object as default, after ensuring it fulfills the
|
||||
* query. The latter may cause some properties of the object to be set,
|
||||
|
|
@ -93,13 +93,13 @@ namespace mobject
|
|||
* @note only a weak ref to the object is stored
|
||||
*/
|
||||
template<class TAR>
|
||||
bool define (const shared_ptr<TAR>&, const lumiera::Query<TAR>&);
|
||||
bool define (const P<TAR>&, const lumiera::Query<TAR>&);
|
||||
|
||||
/** remove the defaults registration of the given object, if there was such
|
||||
* @return false if nothing has been changed because the object wasn't registered
|
||||
*/
|
||||
template<class TAR>
|
||||
bool forget (const shared_ptr<TAR>&);
|
||||
bool forget (const P<TAR>&);
|
||||
|
||||
|
||||
// Q: can we have something along the line of...?
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
#include "common/multithread.hpp"
|
||||
#include "common/query.hpp"
|
||||
#include "common/util.hpp"
|
||||
#include "common/p.hpp"
|
||||
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
|
@ -41,10 +42,10 @@ namespace mobject
|
|||
{
|
||||
namespace session
|
||||
{
|
||||
using std::tr1::shared_ptr;
|
||||
using std::tr1::weak_ptr;
|
||||
using lumiera::Thread;
|
||||
using lumiera::P;
|
||||
using lumiera::Query;
|
||||
using lumiera::Thread;
|
||||
using std::tr1::weak_ptr;
|
||||
|
||||
using std::string;
|
||||
using boost::format;
|
||||
|
|
@ -60,7 +61,7 @@ namespace mobject
|
|||
|
||||
/** we maintain an independent defaults registry
|
||||
* for every participating kind of objects */
|
||||
typedef std::vector<shared_ptr<TableEntry> > Table;
|
||||
typedef std::vector< P<TableEntry> > Table;
|
||||
|
||||
uint maxSlots (0); ///< number of different registered Types
|
||||
|
||||
|
|
@ -76,7 +77,7 @@ namespace mobject
|
|||
Query<TAR> query;
|
||||
weak_ptr<TAR> objRef;
|
||||
|
||||
Record (const Query<TAR>& q, const shared_ptr<TAR>& obj)
|
||||
Record (const Query<TAR>& q, const P<TAR>& obj)
|
||||
: degree (lumiera::query::countPraed (q)),
|
||||
query (q),
|
||||
objRef (obj)
|
||||
|
|
@ -85,15 +86,15 @@ namespace mobject
|
|||
|
||||
struct Search ///< Functor searching for a specific object
|
||||
{
|
||||
Search (const shared_ptr<TAR>& obj)
|
||||
Search (const P<TAR>& obj)
|
||||
: obj_(obj) { }
|
||||
|
||||
const shared_ptr<TAR>& obj_;
|
||||
const P<TAR>& obj_;
|
||||
|
||||
bool
|
||||
operator() (const Record& rec)
|
||||
{
|
||||
shared_ptr<TAR> storedObj (rec.objRef.lock());
|
||||
P<TAR> storedObj (rec.objRef.lock());
|
||||
return storedObj && (storedObj == obj_);
|
||||
}
|
||||
};
|
||||
|
|
@ -110,7 +111,7 @@ namespace mobject
|
|||
};
|
||||
|
||||
operator string () const { return str (dumpRecord % degree % query % dumpObj()); }
|
||||
string dumpObj () const { shared_ptr<TAR> o (objRef.lock()); return o? string(*o):"dead"; }
|
||||
string dumpObj () const { P<TAR> o (objRef.lock()); return o? string(*o):"dead"; }
|
||||
};
|
||||
|
||||
/** every new kind of object (Type) creates a new
|
||||
|
|
@ -186,7 +187,7 @@ namespace mobject
|
|||
typedef typename Slot<TAR>::Registry::iterator II;
|
||||
|
||||
II p,i,e;
|
||||
shared_ptr<TAR> next, ptr;
|
||||
P<TAR> next, ptr;
|
||||
|
||||
Iter (II from, II to) ///< just ennumerates the given range
|
||||
: p(from), i(from), e(to)
|
||||
|
|
@ -201,7 +202,7 @@ namespace mobject
|
|||
operator++ (); // init to first element (or to null if emty)
|
||||
}
|
||||
|
||||
shared_ptr<TAR> findNext () throw()
|
||||
P<TAR> findNext () throw()
|
||||
{
|
||||
while (!next)
|
||||
{
|
||||
|
|
@ -214,9 +215,9 @@ namespace mobject
|
|||
|
||||
|
||||
public:
|
||||
shared_ptr<TAR> operator* () { return ptr; }
|
||||
bool hasNext () { return next || findNext(); }
|
||||
Iter operator++ (int) { Iter tmp=*this; operator++(); return tmp; }
|
||||
P<TAR> operator* () { return ptr; }
|
||||
bool hasNext () { return next || findNext(); }
|
||||
Iter operator++ (int) { Iter tmp=*this; operator++(); return tmp; }
|
||||
Iter& operator++ ()
|
||||
{
|
||||
ptr=findNext();
|
||||
|
|
@ -237,7 +238,7 @@ namespace mobject
|
|||
template<class TAR>
|
||||
Iter<TAR> candidates (const Query<TAR>& query)
|
||||
{
|
||||
shared_ptr<TAR> dummy;
|
||||
P<TAR> dummy;
|
||||
Record<TAR> entry (query, dummy);
|
||||
typedef typename Slot<TAR>::Registry Registry;
|
||||
Registry& registry = Slot<TAR>::access(table_);
|
||||
|
|
@ -261,7 +262,7 @@ namespace mobject
|
|||
* case, also the param obj shared-ptr is rebound!
|
||||
*/
|
||||
template<class TAR>
|
||||
bool put (shared_ptr<TAR>& obj, const Query<TAR>& query)
|
||||
bool put (P<TAR>& obj, const Query<TAR>& query)
|
||||
{
|
||||
Record<TAR> entry (query, obj);
|
||||
typedef typename Slot<TAR>::Registry Registry;
|
||||
|
|
@ -272,7 +273,7 @@ namespace mobject
|
|||
if ( pos!=registry.end()
|
||||
&& pos->query == query)
|
||||
{
|
||||
shared_ptr<TAR> storedObj (pos->objRef.lock());
|
||||
P<TAR> storedObj (pos->objRef.lock());
|
||||
if (storedObj)
|
||||
return (storedObj == obj);
|
||||
else
|
||||
|
|
@ -290,7 +291,7 @@ namespace mobject
|
|||
* @return false if the object wasn't registered at all.
|
||||
*/
|
||||
template<class TAR>
|
||||
bool forget (const shared_ptr<TAR>& obj)
|
||||
bool forget (const P<TAR>& obj)
|
||||
{
|
||||
typedef typename Slot<TAR>::Registry Registry;
|
||||
typedef typename Record<TAR>::Search SearchFunc;
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ namespace mobject
|
|||
} // namespace mobject::session
|
||||
|
||||
/** Placement<Effect> defined to be subclass of Placement<MObject> */
|
||||
DEFINE_SPECIALIZED_PLACEMENT (session::Effect);
|
||||
DEFINE_SPECIALIZED_PLACEMENT (session::Effect, MObject);
|
||||
|
||||
} // namespace mobject
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -111,9 +111,12 @@ namespace mobject
|
|||
virtual LocatingPin* clone () const;
|
||||
virtual ~LocatingPin() {};
|
||||
|
||||
protected:
|
||||
// protected:
|
||||
LocatingPin () {};
|
||||
|
||||
//TODO (for working out the buildable interface; ctor should be protected)
|
||||
protected:
|
||||
|
||||
friend class Placement<MObject>;
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ namespace mobject
|
|||
} // namespace mobject::session
|
||||
|
||||
/** Placement<Meta> defined to be subclass of Placement<MObject> */
|
||||
DEFINE_SPECIALIZED_PLACEMENT (session::Meta);
|
||||
DEFINE_SPECIALIZED_PLACEMENT (session::Meta, MObject);
|
||||
|
||||
} // namespace mobject
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ namespace mobject
|
|||
class Track;
|
||||
class Effect;
|
||||
|
||||
typedef shared_ptr<asset::Track> PTrackAsset;
|
||||
typedef P<asset::Track> PTrackAsset;
|
||||
|
||||
|
||||
class MObjectFactory
|
||||
|
|
|
|||
|
|
@ -34,11 +34,13 @@ namespace mobject
|
|||
{
|
||||
namespace session
|
||||
{
|
||||
using lumiera::P;
|
||||
|
||||
class Track;
|
||||
typedef asset::Track TrackAsset;
|
||||
|
||||
typedef shared_ptr<Track> PTrack;
|
||||
typedef shared_ptr<TrackAsset> PTrackAsset;
|
||||
typedef P<Track> PTrack;
|
||||
typedef P<TrackAsset> PTrackAsset;
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -81,7 +83,7 @@ namespace mobject
|
|||
} // namespace mobject::session
|
||||
|
||||
/** Placement<Track> defined to be subclass of Placement<MObject> */
|
||||
DEFINE_SPECIALIZED_PLACEMENT (session::Track);
|
||||
DEFINE_SPECIALIZED_PLACEMENT (session::Track, session::Meta);
|
||||
|
||||
} // namespace mobject
|
||||
#endif
|
||||
|
|
|
|||
213
src/tool/try.cpp
213
src/tool/try.cpp
|
|
@ -8,25 +8,236 @@
|
|||
// 1/08 - working out a static initialisation problem for Visitor (Tag creation)
|
||||
// 1/08 - check 64bit longs
|
||||
// 4/08 - comparison operators on shared_ptr<Asset>
|
||||
// 4/08 - conversions on the value_type used for boost::any
|
||||
// 5/08 - how to guard a downcasting access, so it is compiled in only if the involved types are convertible
|
||||
|
||||
|
||||
#include <nobug.h>
|
||||
#include <iostream>
|
||||
#include <typeinfo>
|
||||
|
||||
#include <boost/type_traits/is_convertible.hpp>
|
||||
#include <boost/type_traits/is_polymorphic.hpp>
|
||||
#include <boost/type_traits/is_base_of.hpp>
|
||||
#include <boost/type_traits/remove_pointer.hpp>
|
||||
#include <boost/type_traits/remove_reference.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
|
||||
|
||||
using std::string;
|
||||
using std::cout;
|
||||
using std::ostream;
|
||||
|
||||
|
||||
using boost::remove_pointer;
|
||||
using boost::remove_reference;
|
||||
using boost::is_convertible;
|
||||
using boost::is_polymorphic;
|
||||
using boost::is_base_of;
|
||||
using boost::enable_if;
|
||||
|
||||
template <typename SRC, typename TAR>
|
||||
struct can_cast : boost::false_type {};
|
||||
|
||||
template <typename SRC, typename TAR>
|
||||
struct can_cast<SRC*,TAR*> { enum { value = is_base_of<SRC,TAR>::value };};
|
||||
|
||||
template <typename SRC, typename TAR>
|
||||
struct can_cast<SRC*&,TAR*> { enum { value = is_base_of<SRC,TAR>::value };};
|
||||
|
||||
template <typename SRC, typename TAR>
|
||||
struct can_cast<SRC&,TAR&> { enum { value = is_base_of<SRC,TAR>::value };};
|
||||
|
||||
|
||||
template <typename T>
|
||||
struct has_RTTI
|
||||
{
|
||||
typedef typename remove_pointer<
|
||||
typename remove_reference<T>::type>::type TPlain;
|
||||
|
||||
enum { value = is_polymorphic<TPlain>::value };
|
||||
};
|
||||
|
||||
template <typename SRC, typename TAR>
|
||||
struct use_dynamic_downcast
|
||||
{
|
||||
enum { value = can_cast<SRC,TAR>::value
|
||||
&& has_RTTI<SRC>::value
|
||||
&& has_RTTI<TAR>::value
|
||||
};
|
||||
};
|
||||
|
||||
template <typename SRC, typename TAR>
|
||||
struct use_static_downcast
|
||||
{
|
||||
enum { value = can_cast<SRC,TAR>::value
|
||||
&& ( !has_RTTI<SRC>::value
|
||||
|| !has_RTTI<TAR>::value
|
||||
)
|
||||
};
|
||||
};
|
||||
|
||||
template <typename SRC, typename TAR>
|
||||
struct use_conversion
|
||||
{
|
||||
enum { value = is_convertible<SRC,TAR>::value
|
||||
&& !( use_static_downcast<SRC,TAR>::value
|
||||
||use_dynamic_downcast<SRC,TAR>::value
|
||||
)
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
template<typename X>
|
||||
struct EmptyVal
|
||||
{
|
||||
static X create()
|
||||
{
|
||||
cout << " NULL() " << __PRETTY_FUNCTION__ <<"\n";
|
||||
return X();
|
||||
}
|
||||
};
|
||||
template<typename X>
|
||||
struct EmptyVal<X*&>
|
||||
{
|
||||
static X*& create()
|
||||
{
|
||||
cout << " NULL & " << __PRETTY_FUNCTION__ <<"\n";
|
||||
static X* null(0);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<typename RET>
|
||||
struct NullAccessor
|
||||
{
|
||||
typedef RET Ret;
|
||||
|
||||
static RET access (...) { return ifEmpty(); }
|
||||
static RET ifEmpty () { return EmptyVal<RET>::create(); }
|
||||
};
|
||||
|
||||
template<typename TAR>
|
||||
struct AccessCasted : NullAccessor<TAR>
|
||||
{
|
||||
using NullAccessor<TAR>::access;
|
||||
|
||||
template<typename ELM>
|
||||
static typename enable_if< use_dynamic_downcast<ELM&,TAR>, TAR>::type
|
||||
access (ELM& elem)
|
||||
{
|
||||
cout << " dynamic " << __PRETTY_FUNCTION__ <<"\n";
|
||||
return dynamic_cast<TAR> (elem);
|
||||
}
|
||||
|
||||
template<typename ELM>
|
||||
static typename enable_if< use_static_downcast<ELM&,TAR>, TAR>::type
|
||||
access (ELM& elem)
|
||||
{
|
||||
cout << " static " << __PRETTY_FUNCTION__ <<"\n";
|
||||
return static_cast<TAR> (elem);
|
||||
}
|
||||
|
||||
template<typename ELM>
|
||||
static typename enable_if< use_conversion<ELM&,TAR>, TAR>::type
|
||||
access (ELM& elem)
|
||||
{
|
||||
cout << " convert " << __PRETTY_FUNCTION__ <<"\n";
|
||||
return elem;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
int main (int argc, char* argv[])
|
||||
struct B {};
|
||||
struct D : B {};
|
||||
|
||||
struct E : D
|
||||
{
|
||||
virtual ~E() {};
|
||||
};
|
||||
struct F : E {};
|
||||
|
||||
|
||||
ostream& operator<< (ostream& s, const B& b) { return s << "B{} adr="<<&b; }
|
||||
ostream& operator<< (ostream& s, const D& d) { return s << "D{} adr="<<&d; }
|
||||
ostream& operator<< (ostream& s, const E& e) { return s << "E{} adr="<<&e; }
|
||||
ostream& operator<< (ostream& s, const F& f) { return s << "F{} adr="<<&f; }
|
||||
|
||||
int
|
||||
main (int argc, char* argv[])
|
||||
{
|
||||
|
||||
NOBUG_INIT;
|
||||
|
||||
D d;
|
||||
D* pD =&d;
|
||||
B* pB =pD;
|
||||
D& rD = *pD;
|
||||
B& rB = *pB;
|
||||
|
||||
D*& rpD = pD;
|
||||
B*& rpB = pB;
|
||||
|
||||
F f;
|
||||
E& rE = f;
|
||||
E* pE = &f;
|
||||
D* pDE = pE;
|
||||
|
||||
cout << "is_base_of<B,D> = " << is_base_of<B ,D >::value << "\n";
|
||||
cout << "is_base_of<B*,D*> = " << is_base_of<B*,D*>::value << "\n";
|
||||
cout << "is_base_of<B&,D&> = " << is_base_of<B&,D&>::value << "\n";
|
||||
|
||||
cout << "can_cast<B,D> = " << can_cast<B,D>::value << "\n";
|
||||
cout << "can_cast<B*,D*> = " << can_cast<B*,D*>::value << "\n";
|
||||
cout << "can_cast<B&,D&> = " << can_cast<B&,D&>::value << "\n";
|
||||
cout << "can_cast<B&,D*> = " << can_cast<B&,D*>::value << "\n";
|
||||
cout << "can_cast<B*,D&> = " << can_cast<B*,D&>::value << "\n";
|
||||
cout << "can_cast<B*&,D*&> = " << can_cast<B*&,D*&>::value << "\n";
|
||||
cout << "can_cast<D*&,D*&> = " << can_cast<D*&,D*&>::value << "\n";
|
||||
|
||||
cout << "can_cast<D*,E*> = " << can_cast<D*,E*>::value << "\n";
|
||||
cout << "can_cast<E*,F*> = " << can_cast<E*,F*>::value << "\n";
|
||||
|
||||
cout << "has_RTTI<D*> = " << has_RTTI<D*>::value << "\n";
|
||||
cout << "has_RTTI<E*> = " << has_RTTI<E*>::value << "\n";
|
||||
cout << "has_RTTI<F*> = " << has_RTTI<F*>::value << "\n";
|
||||
|
||||
|
||||
cout << "use_dynamic_downcast<B*,D*> = " << use_dynamic_downcast<B*,D*>::value << "\n";
|
||||
cout << "use_static_downcast<B*,D*> = " << use_static_downcast<B*,D*>::value << "\n";
|
||||
cout << "use_conversion<D*,B*> = " << use_conversion<D*,B*>::value << "\n";
|
||||
|
||||
cout << "use_static_downcast<D*&,D*&> = " << use_static_downcast<D*&,D*&>::value << "\n";
|
||||
cout << "use_static_downcast<D*,E*> = " << use_static_downcast<D*,E*>::value << "\n";
|
||||
cout << "use_dynamic_downcast<D*&,E*> = " << use_dynamic_downcast<D*&,E*>::value << "\n";
|
||||
|
||||
|
||||
cout << "Access(D as D&) --->" << AccessCasted<D&>::access(d) << "\n";
|
||||
cout << "Access(D& as D&) --->" << AccessCasted<D&>::access(rD) << "\n";
|
||||
cout << "Access(B& as D&) --->" << AccessCasted<D&>::access(rB) << "\n";
|
||||
cout << "Access(D* as D*) --->" << AccessCasted<D*>::access(pD) << "\n";
|
||||
cout << "Access(B* as D*) --->" << AccessCasted<D*>::access(pB) << "\n";
|
||||
cout << "Access(D*& as D*&) --->" << AccessCasted<D*&>::access(rpD) << "\n";
|
||||
cout << "Access(B*& as D*&) --->" << AccessCasted<D*&>::access(rpB) << "\n";
|
||||
|
||||
cout << "Access(D as B&) --->" << AccessCasted<B&>::access(d) << "\n";
|
||||
cout << "Access(D& as B&) --->" << AccessCasted<B&>::access(rD) << "\n";
|
||||
cout << "Access(B& as B&) --->" << AccessCasted<D&>::access(rB) << "\n";
|
||||
cout << "Access(D* as B*) --->" << AccessCasted<B*>::access(pD) << "\n";
|
||||
cout << "Access(B* as B*) --->" << AccessCasted<B*>::access(pB) << "\n";
|
||||
cout << "Access(D*& as B*&) --->" << AccessCasted<B*&>::access(rpD) << "\n";
|
||||
cout << "Access(B*& as B*&) --->" << AccessCasted<B*&>::access(rpB) << "\n";
|
||||
|
||||
cout << "Access(D as E&) --->" << AccessCasted<E&>::access(d) << "\n";
|
||||
cout << "Access(E& as F&) --->" << AccessCasted<F&>::access(rE) << "\n";
|
||||
cout << "Access(D(E)* as E*) --->" << AccessCasted<E*>::access(pDE) << "\n";
|
||||
cout << "Access(D(E)* as F*) --->" << AccessCasted<F*>::access(pDE) << "\n";
|
||||
cout << "Access(E* as F*) --->" << AccessCasted<F*>::access(pE) << "\n";
|
||||
|
||||
cout << "\ngulp\n";
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -4,8 +4,12 @@ TESTING "Component Test Suite: Builder" ./test-components --group=builder
|
|||
|
||||
|
||||
TEST "BuilderTool_test" BuilderTool_test <<END
|
||||
out: media is: Asset(VIDEO:lumi.test-1 v1)
|
||||
out: catch-all-function called.
|
||||
out: apply (tool, clip);
|
||||
out: Clip on media : Asset(VIDEO:lumi.test-1 v1)
|
||||
out: apply (tool, test1);
|
||||
out: treat (AbstractMO&);
|
||||
out: apply (tool, test2);
|
||||
out: catch-all-function called...
|
||||
END
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
BuilderTool(Test) - specialized form of the acyclic visitor
|
||||
BuilderTool(Test) - specialized visitor used within the builder for processing Placements
|
||||
|
||||
Copyright (C) Lumiera.org
|
||||
2008, Hermann Vosseler <Ichthyostega@web.de>
|
||||
|
|
@ -22,63 +22,127 @@
|
|||
|
||||
|
||||
#include "common/test/run.hpp"
|
||||
|
||||
#include "proc/mobject/builder/buildertool.hpp"
|
||||
#include "proc/mobject/placement.hpp"
|
||||
#include "proc/asset/category.hpp"
|
||||
#include "proc/asset/media.hpp"
|
||||
#include "proc/mobject/session/clip.hpp"
|
||||
#include "common/util.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
using util::cStr;
|
||||
using std::string;
|
||||
using std::cout;
|
||||
|
||||
|
||||
namespace mobject
|
||||
{
|
||||
namespace builder
|
||||
{
|
||||
namespace test
|
||||
{
|
||||
|
||||
namespace mobject {
|
||||
namespace builder {
|
||||
namespace test {
|
||||
|
||||
using session::Clip;
|
||||
using session::AbstractMO;
|
||||
|
||||
|
||||
class DummyMO : public AbstractMO
|
||||
|
||||
|
||||
/**
|
||||
* Test MObject subclass, which, contrary to any real MObject,
|
||||
* can be created directly without involving MObjectFactory.
|
||||
*/
|
||||
class TestMO : public AbstractMO
|
||||
{
|
||||
public:
|
||||
DummyMO() { };
|
||||
virtual bool isValid() const { return true;}
|
||||
TestMO() { };
|
||||
|
||||
DEFINE_PROCESSABLE_BY (BuilderTool);
|
||||
|
||||
virtual bool isValid() const { return true;}
|
||||
static void killDummy (MObject* dum) { delete (TestMO*)dum; }
|
||||
};
|
||||
|
||||
/**
|
||||
* Subclass-1 is \em not defined "processable",
|
||||
* thus will always be handled as TestMO...
|
||||
*/
|
||||
class TestSubMO1 : public TestMO
|
||||
{ };
|
||||
|
||||
/**
|
||||
* Subclass-2 \em is defined "processable",
|
||||
* but we omit the necessary "applicable" definition in TestTool,
|
||||
* resulting in an invocation of the error (catch-all) function...
|
||||
*/
|
||||
class TestSubMO2 : public TestMO
|
||||
{
|
||||
DEFINE_PROCESSABLE_BY (BuilderTool);
|
||||
};
|
||||
|
||||
class TestTool
|
||||
: public Applicable<TestTool, Types<Clip,AbstractMO>::List>
|
||||
|
||||
|
||||
template<class MO>
|
||||
class TestPlacement : public Placement<MO>
|
||||
{
|
||||
public:
|
||||
void treat (Clip& c) { cout << "media is: "<< str(c.getMedia()) <<"\n"; }
|
||||
void treat (AbstractMO&){ cout << "unspecific MO.\n"; }
|
||||
void onUnknown (Buildable&){ cout << "catch-all-function called.\n"; }
|
||||
TestPlacement(TestMO& testObject)
|
||||
: Placement<MO>::Placement(testObject, &TestMO::killDummy)
|
||||
{ }
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* @test the generic visitor pattern specialized for treating
|
||||
* MObjects in the builder. Because the generic visitor
|
||||
* implementation is already covered by
|
||||
* \link VisitingTool_test, it is sufficient to test
|
||||
* the specialisation to the builder.
|
||||
* \par
|
||||
/**
|
||||
* BuilderTool implementation for checking the invokation of the correct
|
||||
* \c treat() function and for accessing the original Placement from
|
||||
* within this invocation. It is declared to be applicable to Clip
|
||||
* and TestMO objects (wrapped into any acceptable shared-ptr).
|
||||
* Intentionally, we omit to declare it applicable to TestSubMO2 instances.
|
||||
* In reality this would be a case of misconfiguration, because TestSubMO2
|
||||
* is defined to be processable and consequently has an \apply() function,
|
||||
* which, due to this ommission can't find a dispatcher entry when invoked,
|
||||
* so it will call the \c onUnknown(Buildable&) instead
|
||||
*/
|
||||
class TestTool
|
||||
: public Applicable<TestTool, Types<Clip, TestMO>::List>
|
||||
{
|
||||
public:
|
||||
string log_;
|
||||
|
||||
void treat (Clip& c)
|
||||
{
|
||||
Placement<Clip>& pC = getPlacement<Clip>();
|
||||
cout << "Clip on media : "<< str(pC->getMedia()) <<"\n";
|
||||
log_ = string (pC);
|
||||
}
|
||||
void treat (AbstractMO&)
|
||||
{
|
||||
cout << "treat (AbstractMO&);\n";
|
||||
log_ = string (getPlacement<MObject>());
|
||||
}
|
||||
void onUnknown (Buildable& bxx)
|
||||
{
|
||||
cout << "catch-all-function called...\n";
|
||||
log_ = string (getPlacement<MObject>());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*************************************************************************************
|
||||
* @test the generic visitor pattern specialized for treating MObjects in the builder.
|
||||
* Besides using existing MObject types (at the moment session::Clip),
|
||||
* we create inline a yet-unknown new MObject subclass. When passing
|
||||
* such to any BuilderTool subclass, the compiler enforces the definition
|
||||
* of a catch-all function, which is called, when there is no other
|
||||
* applicable \c treat(MO&) function. Note further, whithin the specific
|
||||
* treat-functions we get direct references, whithout interfering with
|
||||
* Placements and memory management. (Is this a good idea? it allows
|
||||
* client code to bypass the Placement (Handle). At least, I think
|
||||
* it is not really a problem...)
|
||||
* we create a yet-unknown new MObject subclass. When passing such to any
|
||||
* BuilderTool subclass, the compiler enforces the definition of a catch-all
|
||||
* function, which is called, when there is no other applicable \c treat(MO&)
|
||||
* function. Note further, whithin the specific treat-functions we get direct
|
||||
* references, whithout interfering with Placements and memory management.
|
||||
* But from within the \c treat() function, we may access the wrapper object
|
||||
* (i.e. shared_ptr, or lumiera::P or Placement) used when invoking the
|
||||
* BuilderTool by using the protected interface on BuilderTool.
|
||||
*
|
||||
* @see VisitingTool_test for checking general visitor functionality
|
||||
*/
|
||||
class BuilderTool_test : public Test
|
||||
{
|
||||
|
|
@ -86,13 +150,27 @@ namespace mobject
|
|||
{
|
||||
|
||||
TestTool t1;
|
||||
BuilderTool& tool (t1);
|
||||
BuilderTool& tool = t1;
|
||||
|
||||
DummyMO dumm;
|
||||
PMO clip = asset::Media::create("test-1", asset::VIDEO)->createClip();
|
||||
Placement<Clip> clip = asset::Media::create("test-1", asset::VIDEO)->createClip();
|
||||
TestPlacement<MObject> test1(*new TestSubMO1);
|
||||
TestPlacement<MObject> test2(*new TestSubMO2);
|
||||
|
||||
|
||||
clip->apply (tool);
|
||||
dumm.apply (tool);
|
||||
cout << "apply (tool, clip);\n";
|
||||
apply (tool, clip);
|
||||
INFO (test, "got Wrapper = %s", t1.log_.c_str());
|
||||
ASSERT (t1.log_ == string(clip));
|
||||
|
||||
cout << "apply (tool, test1);\n";
|
||||
apply (tool, test1);
|
||||
INFO (test, "got Wrapper = %s", t1.log_.c_str());
|
||||
ASSERT (t1.log_ == string(test1));
|
||||
|
||||
cout << "apply (tool, test2);\n";
|
||||
apply (tool, test2);
|
||||
INFO (test, "got Wrapper = %s", t1.log_.c_str());
|
||||
ASSERT (t1.log_ == string(test2));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -105,5 +183,5 @@ namespace mobject
|
|||
} // namespace test
|
||||
|
||||
} // namespace builder
|
||||
|
||||
|
||||
} // namespace mobject
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#include "proc/mobject/session/defsregistry.hpp"
|
||||
#include "common/factory.hpp"
|
||||
#include "common/query.hpp"
|
||||
#include "common/p.hpp"
|
||||
|
||||
#include "../common/query/querydiagnostics.hpp"
|
||||
|
||||
|
|
@ -35,11 +36,11 @@
|
|||
#include <cstdlib>
|
||||
#include <map>
|
||||
|
||||
using lumiera::P;
|
||||
using lumiera::Query;
|
||||
using lumiera::query::test::garbage_query;
|
||||
using util::isnil;
|
||||
|
||||
using std::tr1::shared_ptr;
|
||||
using boost::scoped_ptr;
|
||||
using boost::format;
|
||||
using std::string;
|
||||
|
|
@ -75,7 +76,9 @@ namespace mobject
|
|||
{
|
||||
static string name;
|
||||
string instanceID;
|
||||
operator string () const { return instanceID; }
|
||||
operator string () const { return instanceID; }
|
||||
bool operator== (const Dummy& odu) const { return this == &odu; }
|
||||
|
||||
|
||||
Dummy () : instanceID (newID (name)) {}
|
||||
};
|
||||
|
|
@ -99,8 +102,8 @@ namespace mobject
|
|||
{
|
||||
scoped_ptr<DefsRegistry> reg_;
|
||||
|
||||
typedef shared_ptr<Dummy<13> > O;
|
||||
typedef shared_ptr<Dummy<23> > P;
|
||||
typedef P<Dummy<13> > O;
|
||||
typedef P<Dummy<23> > P;
|
||||
|
||||
typedef Query<Dummy<13> > Q13;
|
||||
typedef Query<Dummy<23> > Q23;
|
||||
|
|
|
|||
Loading…
Reference in a new issue