1
//---------------------------------------------------------------------------
3
// Project: OpenWalnut ( http://www.openwalnut.org )
5
// Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
6
// For more information see http://www.openwalnut.org/copying
8
// This file is part of OpenWalnut.
10
// OpenWalnut is free software: you can redistribute it and/or modify
11
// it under the terms of the GNU Lesser General Public License as published by
12
// the Free Software Foundation, either version 3 of the License, or
13
// (at your option) any later version.
15
// OpenWalnut is distributed in the hope that it will be useful,
16
// but WITHOUT ANY WARRANTY; without even the implied warranty of
17
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
// GNU Lesser General Public License for more details.
20
// You should have received a copy of the GNU Lesser General Public License
21
// along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
23
//---------------------------------------------------------------------------
25
#ifndef WPROPERTYSTRUCT_H
26
#define WPROPERTYSTRUCT_H
31
#include <boost/shared_ptr.hpp>
33
#include <boost/tuple/tuple.hpp>
34
#include <boost/mpl/vector.hpp>
35
#include <boost/mpl/copy.hpp>
36
#include <boost/mpl/size.hpp>
37
#include <boost/mpl/at.hpp>
38
#include <boost/preprocessor/repetition/enum_params.hpp>
40
#include "WStringUtils.h"
41
#include "WCondition.h"
42
#include "WPropertyGroupBase.h"
43
#include "WPropertyBase.h"
44
#include "WPropertyTypes.h"
45
#include "exceptions/WPropertyUnknown.h"
48
* This contains some helping classes for compile time type conversion and similar.
50
namespace WPropertyStructHelper
53
* Class to push a type from a sequence to the front of a tuple type
55
* \tparam T the sequence to convert.
56
* \tparam Tuple the tuple type, getting extended with the sequence types.
58
template< typename T, typename Tuple>
59
struct PushTypeToTupleFront;
62
* Class to push a type from a sequence to the front of a tuple type. This is a specialization allowing to create a tuple from a list of
65
* \tparam T the sequence to convert.
66
* \tparam list of types to add to the tuple.
68
template< typename T, BOOST_PP_ENUM_PARAMS( 10, typename T )>
69
struct PushTypeToTupleFront< T, boost::tuple< BOOST_PP_ENUM_PARAMS( 10, T ) > >
72
* The resulting tuple type
74
typedef boost::tuple< T, BOOST_PP_ENUM_PARAMS( 9, T ) > type;
78
* Converts a boost mpl sequence to a boost tuple
80
* \tparam Sequence the sequence to convert
82
template< typename Sequence >
83
struct SequenceToTuple
86
* This is the tuple type for the sequence
88
typedef typename boost::mpl::reverse_copy<
92
PushTypeToTupleFront< boost::mpl::_2, boost::mpl::_1 >
98
* Alias for default type to emulate variadic templates
100
typedef boost::mpl::na NOTYPE;
103
* Convert a list of template parameters to a boost::mpl::vector. This is currently done using the boost::mpl no-type type. This might get a
106
* \tparam T0 first type. Mandatory.
107
* \tparam T1 additional type. Optional.
108
* \tparam T2 additional type. Optional.
109
* \tparam T3 additional type. Optional.
110
* \tparam T4 additional type. Optional.
111
* \tparam T5 additional type. Optional.
112
* \tparam T6 additional type. Optional.
113
* \tparam T7 additional type. Optional.
114
* \tparam T8 additional type. Optional.
115
* \tparam T9 additional type. Optional.
119
typename T1 = NOTYPE,
120
typename T2 = NOTYPE,
121
typename T3 = NOTYPE,
122
typename T4 = NOTYPE,
123
typename T5 = NOTYPE,
124
typename T6 = NOTYPE,
125
typename T7 = NOTYPE,
126
typename T8 = NOTYPE,
132
* The template types as mpl vector
134
typedef boost::mpl::vector< BOOST_PP_ENUM_PARAMS( 10, T ) > type;
139
* Specialization which does nothing for the NOTYPE default template parameters of \ref WPropertyStruct.
142
struct WPropertyGroupBase::PropertyCreatorAndGroupAdder< WPropertyStructHelper::NOTYPE >
145
* The type of the initial value.
147
typedef WPropertyStructHelper::NOTYPE ValueType;
150
* Dummy method which does nothing for NOTYPE types.
152
static void createAndAdd( WPropertyGroupBase*, std::string, std::string, const ValueType& )
154
// NOTYPE will not cause any property creation.
158
* Dummy method which does nothing for NOTYPE types.
160
static void createAndAdd( WPropertyGroupBase*, std::string, std::string )
162
// NOTYPE will not cause any property creation.
168
* This is a property which encapsulates a given, fixed number of other properties. You can specify up to 10 properties. This can be seen
169
* similar to the "struct" in the C++ language. A WPropertyStruct can basically seen as \ref WPropertyGroup, but is different in a certain way:
170
* it is fixed size (defined on compile time), it allows getting each property with their correct type and provides the appearance as if this
171
* property is only ONE object and not a group of multiple objects.
173
* \note the limitation to 10 types is due to the boost::tuple. If you need more, you need to replace the tuple type as storage-backend.
174
* \note if we use C++11 some day, we could use variadic templates here.
176
* \tparam T0 first type. Mandatory.
177
* \tparam T1 additional type. Optional.
178
* \tparam T2 additional type. Optional.
179
* \tparam T3 additional type. Optional.
180
* \tparam T4 additional type. Optional.
181
* \tparam T5 additional type. Optional.
182
* \tparam T6 additional type. Optional.
183
* \tparam T7 additional type. Optional.
184
* \tparam T8 additional type. Optional.
185
* \tparam T9 additional type. Optional.
189
typename T1 = WPropertyStructHelper::NOTYPE,
190
typename T2 = WPropertyStructHelper::NOTYPE,
191
typename T3 = WPropertyStructHelper::NOTYPE,
192
typename T4 = WPropertyStructHelper::NOTYPE,
193
typename T5 = WPropertyStructHelper::NOTYPE,
194
typename T6 = WPropertyStructHelper::NOTYPE,
195
typename T7 = WPropertyStructHelper::NOTYPE,
196
typename T8 = WPropertyStructHelper::NOTYPE,
197
typename T9 = WPropertyStructHelper::NOTYPE
199
class WPropertyStruct: public WPropertyGroupBase
201
friend class WPropertyStructTest;
204
* The type of this template instantiation.
206
typedef WPropertyStruct< BOOST_PP_ENUM_PARAMS( 10, T ) > WPropertyStructType;
209
* Convenience typedef for a boost::shared_ptr< WPropertyStructType >
211
typedef typename boost::shared_ptr< WPropertyStructType > SPtr;
214
* Convenience typedef for a boost::shared_ptr< const WPropertyStructType >
216
typedef typename boost::shared_ptr< const WPropertyStructType > ConstSPtr;
219
* The boost mpl vector for all the types specified.
221
typedef typename WPropertyStructHelper::AsVector< BOOST_PP_ENUM_PARAMS( 10, T ) >::type TypeVector;
224
* The type vector as a boost tuple.
226
typedef typename WPropertyStructHelper::SequenceToTuple< TypeVector >::type TupleType;
229
* Create an empty named property.
231
* \param name the name of the property
232
* \param description the description of the property
234
WPropertyStruct( std::string name, std::string description ):
235
WPropertyGroupBase( name, description )
237
// now create the property instances
238
PropertyCreatorAndGroupAdder< T0 >::createAndAdd( this, name + "_Prop0", "No description for Property 0 in struct \"" + name + "\"." );
239
PropertyCreatorAndGroupAdder< T1 >::createAndAdd( this, name + "_Prop1", "No description for Property 1 in struct \"" + name + "\"." );
240
PropertyCreatorAndGroupAdder< T2 >::createAndAdd( this, name + "_Prop2", "No description for Property 2 in struct \"" + name + "\"." );
241
PropertyCreatorAndGroupAdder< T3 >::createAndAdd( this, name + "_Prop3", "No description for Property 3 in struct \"" + name + "\"." );
242
PropertyCreatorAndGroupAdder< T4 >::createAndAdd( this, name + "_Prop4", "No description for Property 4 in struct \"" + name + "\"." );
243
PropertyCreatorAndGroupAdder< T5 >::createAndAdd( this, name + "_Prop5", "No description for Property 5 in struct \"" + name + "\"." );
244
PropertyCreatorAndGroupAdder< T6 >::createAndAdd( this, name + "_Prop6", "No description for Property 6 in struct \"" + name + "\"." );
245
PropertyCreatorAndGroupAdder< T7 >::createAndAdd( this, name + "_Prop7", "No description for Property 7 in struct \"" + name + "\"." );
246
PropertyCreatorAndGroupAdder< T8 >::createAndAdd( this, name + "_Prop8", "No description for Property 8 in struct \"" + name + "\"." );
247
PropertyCreatorAndGroupAdder< T9 >::createAndAdd( this, name + "_Prop9", "No description for Property 9 in struct \"" + name + "\"." );
251
* Copy constructor. Creates a deep copy of this property. As boost::signals2 and condition variables are non-copyable, new instances get
252
* created. The subscriptions to a signal are LOST as well as all listeners to a condition.
254
* \param from the instance to copy.
256
explicit WPropertyStruct( const WPropertyStructType& from ):
257
WPropertyGroupBase( from )
259
// this created a NEW update condition and NEW property instances (clones)
265
virtual ~WPropertyStruct()
267
// the storing tuple is destroyed automatically and the properties if not used anymore
271
* Get the N'th property in the struct.
273
* \tparam N the number of the property to get.
275
* \return the property.
278
typename boost::mpl::at< TypeVector, boost::mpl::size_t< N > >::type getProperty()
280
typedef typename boost::mpl::at< TypeVector, boost::mpl::size_t< N > >::type::element_type TargetType;
281
return boost::shared_dynamic_cast< TargetType >( getProperty( N ) );
285
* Get the N'th property in the struct.
287
* \tparam N the number of the property to get.
289
* \return the property.
292
typename boost::mpl::at< TypeVector, boost::mpl::size_t< N > >::type::element_type::ConstSPtr getProperty() const
294
typedef typename boost::mpl::at< TypeVector, boost::mpl::size_t< N > >::type::element_type TargetType;
295
return boost::shared_dynamic_cast< const TargetType >( getProperty( N ) );
299
* Returns the property with the given number, but only as base type. The advantage is that the property number can be specified during
302
* \param n the number of the property
304
* \return the property
306
const WPropertyBase::SPtr& getProperty( size_t n ) const
308
// lock, unlocked if l looses focus
309
PropertySharedContainerType::ReadTicket l = m_properties.getReadTicket();
310
return l->get()[ n ];
314
* Returns the property with the given number, but only as base type. The advantage is that the property number can be specified during
317
* \param n the number of the property
319
* \return the property
321
WPropertyBase::SPtr getProperty( size_t n )
323
// lock, unlocked if l looses focus
324
PropertySharedContainerType::ReadTicket l = m_properties.getReadTicket();
325
return l->get()[ n ];
329
* The size of the WPropertyStruct. This returns the number of properties encapsulated.
331
* \return number of properties in struct
338
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
339
// The WPropertyBase specific stuff
340
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
343
* This method clones a property and returns the clone. It does a deep copy and, in contrast to a copy constructor, creates property with the
344
* correct type without explicitly requiring the user to specify it. It creates a NEW change condition and change signal. This means, alls
345
* subscribed signal handlers are NOT copied.
347
* \note this simply ensures the copy constructor of the runtime type is issued.
349
* \return the deep clone of this property.
351
virtual WPropertyBase::SPtr clone()
353
// just use the copy constructor
354
return typename WPropertyStructType::SPtr( new WPropertyStructType( *this ) );
358
* Gets the real WPropertyVariable type of this instance.
360
* \return the real type.
362
virtual PROPERTY_TYPE getType() const
368
* This methods allows properties to be set by a string value. This is especially useful when a property is only available as string and the
369
* real type of the property is unknown. This is a shortcut for casting the property and then setting the lexically casted value.
371
* \param value the new value to set.
373
* \return true if value could be set.
375
virtual bool setAsString( std::string value )
377
// this method splits the given string and simply forwards the call to the other properties
378
std::vector< std::string > propsAsString = string_utils::tokenize( value, "|", false );
379
if( size() != propsAsString.size() )
384
// lock, unlocked if l looses focus
385
PropertySharedContainerType::ReadTicket l = m_properties.getReadTicket();
386
// give the string to each property
387
size_t curPropNb = 0;
389
for( std::vector< std::string >::const_iterator iter = propsAsString.begin(); iter != propsAsString.end(); ++iter )
391
success = success && l->get()[ curPropNb ]->setAsString( *iter );
398
* Returns the current value as a string. This is useful for debugging or project files. It is not implemented as << operator, since the <<
399
* should also print min/max constraints and so on. This simply is the value.
401
* \return the value as a string.
403
virtual std::string getAsString()
405
// lock, unlocked if l looses focus
406
PropertySharedContainerType::ReadTicket l = m_properties.getReadTicket();
408
// go through and append each prop
409
std::string result = "";
410
for( size_t i = 0; i < size(); ++i )
412
result += l->get()[ i ]->getAsString() + "|";
415
result.erase( result.length() - 1, 1 );
420
* Sets the value from the specified property to this one. This is especially useful to copy a value without explicitly casting/knowing the
421
* dynamic type of the property.
423
* \param value the new value.
424
* \param recommendedOnly if true, property types which support recommended values apply the given value as recommendation.
426
* \return true if the value has been accepted.
428
virtual bool set( boost::shared_ptr< WPropertyBase > value, bool recommendedOnly = false )
430
// is this the same type as we are?
431
typename WPropertyStructType::SPtr v = boost::shared_dynamic_cast< WPropertyStructType >( value );
434
// it is not a WPropertyStruct with the same type
438
// lock, unlocked if l looses focus
439
PropertySharedContainerType::ReadTicket l = m_properties.getReadTicket();
440
PropertySharedContainerType::ReadTicket lother = v->m_properties.getReadTicket();
443
for( size_t curPropNb = 0; curPropNb < size(); ++curPropNb )
445
success = success && l->get()[ curPropNb ]->set( lother->get()[ curPropNb ], recommendedOnly );
454
* How many elements are in this WPropertyStruct?
456
static const size_t m_size = boost::mpl::size< TypeVector >::value;
459
#endif // WPROPERTYSTRUCT_H