1 /*=========================================================================
3 Module: $RCSfile: bbstdMagicBox.h,v $
5 Date: $Date: 2009/03/30 14:42:23 $
6 Version: $Revision: 1.11 $
7 =========================================================================*/
9 /* ---------------------------------------------------------------------
11 * Copyright (c) CREATIS-LRMN (Centre de Recherche en Imagerie Medicale)
12 * Authors : Eduardo Davila, Laurent Guigues, Jean-Pierre Roux
14 * This software is governed by the CeCILL-B license under French law and
15 * abiding by the rules of distribution of free software. You can use,
16 * modify and/ or redistribute the software under the terms of the CeCILL-B
17 * license as circulated by CEA, CNRS and INRIA at the following URL
18 * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
19 * or in the file LICENSE.txt.
21 * As a counterpart to the access to the source code and rights to copy,
22 * modify and redistribute granted by the license, users are provided only
23 * with a limited warranty and the software's author, the holder of the
24 * economic rights, and the successive licensors have only limited
27 * The fact that you are presently reading this means that you have had
28 * knowledge of the CeCILL-B license and that you accept its terms.
29 * ------------------------------------------------------------------------ */
32 #ifndef __bbstdMagicBox_h_INCLUDED_H__
33 #define __bbstdMagicBox_h_INCLUDED_H__
35 #include "bbtkAtomicBlackBox.h"
36 #include "bbstd_EXPORT.h"
40 #define BBTK_MB_DECLARE_INPUT(NAME,TYPE) \
42 TYPE bbmInput##NAME; \
44 TYPE bbGetInput##NAME () \
45 { return bbmInput##NAME; } \
46 void bbSetInput##NAME (TYPE d) \
47 { bbmInput##NAME = d; \
48 if (mCanSet) { bbSetOutputOut(d); mCanSet = false; } }
50 //==================================================================
51 class bbstd_EXPORT MagicBox
53 public bbtk::AtomicBlackBox
55 BBTK_BLACK_BOX_INTERFACE(MagicBox,bbtk::AtomicBlackBox);
56 BBTK_MB_DECLARE_INPUT(In,bbtk::Data);
57 BBTK_MB_DECLARE_INPUT(In1,bbtk::Data);
58 BBTK_MB_DECLARE_INPUT(In2,bbtk::Data);
59 BBTK_MB_DECLARE_INPUT(In3,bbtk::Data);
60 BBTK_MB_DECLARE_INPUT(In4,bbtk::Data);
61 BBTK_MB_DECLARE_INPUT(In5,bbtk::Data);
62 BBTK_MB_DECLARE_INPUT(In6,bbtk::Data);
63 BBTK_MB_DECLARE_INPUT(In7,bbtk::Data);
64 BBTK_MB_DECLARE_INPUT(In8,bbtk::Data);
65 BBTK_MB_DECLARE_INPUT(In9,bbtk::Data);
66 BBTK_DECLARE_OUTPUT(Out,bbtk::Data);
67 BBTK_PROCESS(DoProcess);
70 // virtual void bbUserConstructor();
71 virtual void bbSetStatusAndPropagate(bbtk::BlackBoxInputConnector* c,
74 virtual void bbUserConstructor() { mCanSet = true; }
77 //==================================================================
79 #undef BBTK_MB_DECLARE_INPUT
81 //==================================================================
82 // We have to create a particular SetFunctor for MagicBox because
83 // its input is of type bbtk::Data (i.e. any) and :
84 // 1) an any cannot store an any (construction with an any invokes the copy constr.)
85 // 2) we cannot invoke the Set method with the content of the any because
87 // hence the Set method of the functor **MUST NOT** extract the
88 // content of the Data prior to invoking the set method of the box
89 class MagicBoxSetFunctor : public bbtk::AtomicBlackBoxSetFunctor
92 /// Type of pointer on a UBB::Set method
93 typedef void (MagicBox::*SetMethodPointerType)(bbtk::Data);
95 /// Construction with the pointer on the Set method
96 MagicBoxSetFunctor(SetMethodPointerType s) :
101 /// Concrete application of the Set method of object o
102 void Set(bbtk::AtomicBlackBox* o, const bbtk::Data& d)
104 bbtkDebugMessage("data",9,"MagicBoxSetfunctor::Set("<<
105 bbtk::HumanTypeName(d.type())<<
107 (((MagicBox*)o)->*mSetMethodPointer)(d);
111 bbtk::TypeInfo GetTypeInfo() const { return typeid(bbtk::Data); }
112 std::string GetTypeName() const { return bbtk::TypeName<bbtk::Data>(); }
113 std::string GetHumanTypeName() const { return bbtk::HumanTypeName<bbtk::Data>(); }
114 bool IsPointerType() const { return false; }
115 void BruteForceSetPointer(bbtk::AtomicBlackBox*, void*) {}
117 /// Pointer on the Set method
118 SetMethodPointerType mSetMethodPointer;
120 //===========================================================================
122 #define MAGIC_BOX_INPUT(NAME) \
124 (new bbtk::AtomicBlackBoxInputDescriptor \
125 (typeid(MagicBoxDescriptor), \
126 #NAME,"Input data","", \
127 new bbtk::AtomicBlackBoxTGetFunctor<MagicBox,bbtk::Data,bbtk::Data> \
128 (&MagicBox::bbGetInput ## NAME), \
129 new MagicBoxSetFunctor (&MagicBox::bbSetInput ## NAME) ) );
131 //===========================================================================
132 BBTK_BEGIN_DESCRIBE_BLACK_BOX(MagicBox,bbtk::AtomicBlackBox);
133 BBTK_NAME("MagicBox");
134 BBTK_AUTHOR("laurent.guigues@creatis.insa-lyon.fr");
135 BBTK_CATEGORY("misc");
136 BBTK_DESCRIPTION("Takes *any kind* of data and copies it to its output. Is a magic box as any box output can be plugged into it and its output can be plugged into any other box input (dynamic type checking, see below), hence it can be put between **any** two boxes. Type matching between its output and the input of the box(es) to which it is connected is made at *run-time*. The pipeline will be executed if the data types : i) match exactly ii) can be transformed by an adaptor iii) are related pointers, i.e. if the output pointer can be upcasted (static_cast) or downcasted (dynamic_cast) to an input type pointer (see the bbtk::any output connection rule in the guide for details). Important uses of the MagicBox are : 1) performing run-time pointer cast, either upward or backward an object hierarchy 2) perform data adaptation (adaptor creation) at run-time vs. pipeline creation time. Any has now 9 more inputs and the value of the output is the value of the lower index input which has changed. This functionality is used to implement a memory which can be written by different boxes. The current value of the memory (the output) is that of the last input which has changed, i.e. has 'written' the memory. It is used for example for synchronization issues between boxes.");
150 (new bbtk::AtomicBlackBoxInputDescriptor
151 (typeid(MagicBoxDescriptor),
152 "In","Input data","",
153 new bbtk::AtomicBlackBoxTGetFunctor<MagicBox,bbtk::Data,bbtk::Data>
154 (&MagicBox::bbGetInputIn),
155 new MagicBoxSetFunctor (&MagicBox::bbSetInputIn) ) );
158 (new bbtk::AtomicBlackBoxOutputDescriptor
159 (typeid(MagicBoxDescriptor),
160 "Out","Output data","",
161 new bbtk::AtomicBlackBoxTGetFunctor<MagicBox,bbtk::Data,bbtk::Data>
162 (&MagicBox::bbGetOutputOut),
163 new MagicBoxSetFunctor (&MagicBox::bbSetOutputOut) ) );
164 BBTK_END_DESCRIBE_BLACK_BOX(MagicBox);
165 //===========================================================================
170 #endif // __bbstdMagicBox_h_INCLUDED_H__