OpenWalnut
1.4.0
|
00001 //--------------------------------------------------------------------------- 00002 // 00003 // Project: OpenWalnut ( http://www.openwalnut.org ) 00004 // 00005 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS 00006 // For more information see http://www.openwalnut.org/copying 00007 // 00008 // This file is part of OpenWalnut. 00009 // 00010 // OpenWalnut is free software: you can redistribute it and/or modify 00011 // it under the terms of the GNU Lesser General Public License as published by 00012 // the Free Software Foundation, either version 3 of the License, or 00013 // (at your option) any later version. 00014 // 00015 // OpenWalnut is distributed in the hope that it will be useful, 00016 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00018 // GNU Lesser General Public License for more details. 00019 // 00020 // You should have received a copy of the GNU Lesser General Public License 00021 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>. 00022 // 00023 //--------------------------------------------------------------------------- 00024 00025 #ifndef WPROPERTYSTRUCT_H 00026 #define WPROPERTYSTRUCT_H 00027 00028 #include <vector> 00029 #include <string> 00030 00031 #include <boost/shared_ptr.hpp> 00032 00033 #include <boost/tuple/tuple.hpp> 00034 #include <boost/mpl/vector.hpp> 00035 #include <boost/mpl/copy.hpp> 00036 #include <boost/mpl/size.hpp> 00037 #include <boost/mpl/at.hpp> 00038 #include <boost/preprocessor/repetition/enum_params.hpp> 00039 00040 #include "WStringUtils.h" 00041 #include "WCondition.h" 00042 #include "WPropertyGroupBase.h" 00043 #include "WPropertyBase.h" 00044 #include "WPropertyTypes.h" 00045 #include "exceptions/WPropertyUnknown.h" 00046 00047 /** 00048 * This contains some helping classes for compile time type conversion and similar. 00049 */ 00050 namespace WPropertyStructHelper 00051 { 00052 /** 00053 * Class to push a type from a sequence to the front of a tuple type 00054 * 00055 * \tparam T the sequence to convert. 00056 * \tparam Tuple the tuple type, getting extended with the sequence types. 00057 */ 00058 template< typename T, typename Tuple> 00059 struct PushTypeToTupleFront; 00060 00061 /** 00062 * 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 00063 * types. 00064 * 00065 * \tparam T the sequence to convert. 00066 * \tparam list of types to add to the tuple. 00067 */ 00068 template< typename T, BOOST_PP_ENUM_PARAMS( 10, typename T )> 00069 struct PushTypeToTupleFront< T, boost::tuple< BOOST_PP_ENUM_PARAMS( 10, T ) > > 00070 { 00071 /** 00072 * The resulting tuple type 00073 */ 00074 typedef boost::tuple< T, BOOST_PP_ENUM_PARAMS( 9, T ) > type; 00075 }; 00076 00077 /** 00078 * Converts a boost mpl sequence to a boost tuple 00079 * 00080 * \tparam Sequence the sequence to convert 00081 */ 00082 template< typename Sequence > 00083 struct SequenceToTuple 00084 { 00085 /** 00086 * This is the tuple type for the sequence 00087 */ 00088 typedef typename boost::mpl::reverse_copy< 00089 Sequence, 00090 boost::mpl::inserter< 00091 boost::tuple<>, 00092 PushTypeToTupleFront< boost::mpl::_2, boost::mpl::_1 > 00093 > 00094 >::type type; 00095 }; 00096 00097 /** 00098 * Alias for default type to emulate variadic templates 00099 */ 00100 typedef boost::mpl::na NOTYPE; 00101 00102 /** 00103 * 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 00104 * problem some day?! 00105 * 00106 * \tparam T0 first type. Mandatory. 00107 * \tparam T1 additional type. Optional. 00108 * \tparam T2 additional type. Optional. 00109 * \tparam T3 additional type. Optional. 00110 * \tparam T4 additional type. Optional. 00111 * \tparam T5 additional type. Optional. 00112 * \tparam T6 additional type. Optional. 00113 * \tparam T7 additional type. Optional. 00114 * \tparam T8 additional type. Optional. 00115 * \tparam T9 additional type. Optional. 00116 */ 00117 template< 00118 typename T0, 00119 typename T1 = NOTYPE, 00120 typename T2 = NOTYPE, 00121 typename T3 = NOTYPE, 00122 typename T4 = NOTYPE, 00123 typename T5 = NOTYPE, 00124 typename T6 = NOTYPE, 00125 typename T7 = NOTYPE, 00126 typename T8 = NOTYPE, 00127 typename T9 = NOTYPE 00128 > 00129 struct AsVector 00130 { 00131 /** 00132 * The template types as mpl vector 00133 */ 00134 typedef boost::mpl::vector< BOOST_PP_ENUM_PARAMS( 10, T ) > type; 00135 }; 00136 } 00137 00138 /** 00139 * Specialization which does nothing for the NOTYPE default template parameters of \ref WPropertyStruct. 00140 */ 00141 template<> 00142 struct WPropertyGroupBase::PropertyCreatorAndGroupAdder< WPropertyStructHelper::NOTYPE > 00143 { 00144 /** 00145 * The type of the initial value. 00146 */ 00147 typedef WPropertyStructHelper::NOTYPE ValueType; 00148 00149 /** 00150 * Dummy method which does nothing for NOTYPE types. 00151 */ 00152 static void createAndAdd( WPropertyGroupBase*, std::string, std::string, const ValueType& ) 00153 { 00154 // NOTYPE will not cause any property creation. 00155 } 00156 00157 /** 00158 * Dummy method which does nothing for NOTYPE types. 00159 */ 00160 static void createAndAdd( WPropertyGroupBase*, std::string, std::string ) 00161 { 00162 // NOTYPE will not cause any property creation. 00163 } 00164 }; 00165 00166 00167 /** 00168 * This is a property which encapsulates a given, fixed number of other properties. You can specify up to 10 properties. This can be seen 00169 * similar to the "struct" in the C++ language. A WPropertyStruct can basically seen as \ref WPropertyGroup, but is different in a certain way: 00170 * it is fixed size (defined on compile time), it allows getting each property with their correct type and provides the appearance as if this 00171 * property is only ONE object and not a group of multiple objects. 00172 * 00173 * \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. 00174 * \note if we use C++11 some day, we could use variadic templates here. 00175 * 00176 * \tparam T0 first type. Mandatory. 00177 * \tparam T1 additional type. Optional. 00178 * \tparam T2 additional type. Optional. 00179 * \tparam T3 additional type. Optional. 00180 * \tparam T4 additional type. Optional. 00181 * \tparam T5 additional type. Optional. 00182 * \tparam T6 additional type. Optional. 00183 * \tparam T7 additional type. Optional. 00184 * \tparam T8 additional type. Optional. 00185 * \tparam T9 additional type. Optional. 00186 */ 00187 template< 00188 typename T0, 00189 typename T1 = WPropertyStructHelper::NOTYPE, 00190 typename T2 = WPropertyStructHelper::NOTYPE, 00191 typename T3 = WPropertyStructHelper::NOTYPE, 00192 typename T4 = WPropertyStructHelper::NOTYPE, 00193 typename T5 = WPropertyStructHelper::NOTYPE, 00194 typename T6 = WPropertyStructHelper::NOTYPE, 00195 typename T7 = WPropertyStructHelper::NOTYPE, 00196 typename T8 = WPropertyStructHelper::NOTYPE, 00197 typename T9 = WPropertyStructHelper::NOTYPE 00198 > 00199 class WPropertyStruct: public WPropertyGroupBase 00200 { 00201 friend class WPropertyStructTest; 00202 public: 00203 /** 00204 * The type of this template instantiation. 00205 */ 00206 typedef WPropertyStruct< BOOST_PP_ENUM_PARAMS( 10, T ) > WPropertyStructType; 00207 00208 /** 00209 * Convenience typedef for a boost::shared_ptr< WPropertyStructType > 00210 */ 00211 typedef typename boost::shared_ptr< WPropertyStructType > SPtr; 00212 00213 /** 00214 * Convenience typedef for a boost::shared_ptr< const WPropertyStructType > 00215 */ 00216 typedef typename boost::shared_ptr< const WPropertyStructType > ConstSPtr; 00217 00218 /** 00219 * The boost mpl vector for all the types specified. 00220 */ 00221 typedef typename WPropertyStructHelper::AsVector< BOOST_PP_ENUM_PARAMS( 10, T ) >::type TypeVector; 00222 00223 /** 00224 * The type vector as a boost tuple. 00225 */ 00226 typedef typename WPropertyStructHelper::SequenceToTuple< TypeVector >::type TupleType; 00227 00228 /** 00229 * Create an empty named property. 00230 * 00231 * \param name the name of the property 00232 * \param description the description of the property 00233 */ 00234 WPropertyStruct( std::string name, std::string description ): 00235 WPropertyGroupBase( name, description ) 00236 { 00237 // now create the property instances 00238 PropertyCreatorAndGroupAdder< T0 >::createAndAdd( this, name + "_Prop0", "No description for Property 0 in struct \"" + name + "\"." ); 00239 PropertyCreatorAndGroupAdder< T1 >::createAndAdd( this, name + "_Prop1", "No description for Property 1 in struct \"" + name + "\"." ); 00240 PropertyCreatorAndGroupAdder< T2 >::createAndAdd( this, name + "_Prop2", "No description for Property 2 in struct \"" + name + "\"." ); 00241 PropertyCreatorAndGroupAdder< T3 >::createAndAdd( this, name + "_Prop3", "No description for Property 3 in struct \"" + name + "\"." ); 00242 PropertyCreatorAndGroupAdder< T4 >::createAndAdd( this, name + "_Prop4", "No description for Property 4 in struct \"" + name + "\"." ); 00243 PropertyCreatorAndGroupAdder< T5 >::createAndAdd( this, name + "_Prop5", "No description for Property 5 in struct \"" + name + "\"." ); 00244 PropertyCreatorAndGroupAdder< T6 >::createAndAdd( this, name + "_Prop6", "No description for Property 6 in struct \"" + name + "\"." ); 00245 PropertyCreatorAndGroupAdder< T7 >::createAndAdd( this, name + "_Prop7", "No description for Property 7 in struct \"" + name + "\"." ); 00246 PropertyCreatorAndGroupAdder< T8 >::createAndAdd( this, name + "_Prop8", "No description for Property 8 in struct \"" + name + "\"." ); 00247 PropertyCreatorAndGroupAdder< T9 >::createAndAdd( this, name + "_Prop9", "No description for Property 9 in struct \"" + name + "\"." ); 00248 } 00249 00250 /** 00251 * Copy constructor. Creates a deep copy of this property. As boost::signals2 and condition variables are non-copyable, new instances get 00252 * created. The subscriptions to a signal are LOST as well as all listeners to a condition. 00253 * 00254 * \param from the instance to copy. 00255 */ 00256 explicit WPropertyStruct( const WPropertyStructType& from ): 00257 WPropertyGroupBase( from ) 00258 { 00259 // this created a NEW update condition and NEW property instances (clones) 00260 } 00261 00262 /** 00263 * Destructor. 00264 */ 00265 virtual ~WPropertyStruct() 00266 { 00267 // the storing tuple is destroyed automatically and the properties if not used anymore 00268 } 00269 00270 /** 00271 * Get the N'th property in the struct. 00272 * 00273 * \tparam N the number of the property to get. 00274 * 00275 * \return the property. 00276 */ 00277 template< int N > 00278 typename boost::mpl::at< TypeVector, boost::mpl::size_t< N > >::type getProperty() 00279 { 00280 typedef typename boost::mpl::at< TypeVector, boost::mpl::size_t< N > >::type::element_type TargetType; 00281 return boost::dynamic_pointer_cast< TargetType >( getProperty( N ) ); 00282 } 00283 00284 /** 00285 * Get the N'th property in the struct. 00286 * 00287 * \tparam N the number of the property to get. 00288 * 00289 * \return the property. 00290 */ 00291 template< int N > 00292 typename boost::mpl::at< TypeVector, boost::mpl::size_t< N > >::type::element_type::ConstSPtr getProperty() const 00293 { 00294 typedef typename boost::mpl::at< TypeVector, boost::mpl::size_t< N > >::type::element_type TargetType; 00295 return boost::dynamic_pointer_cast< const TargetType >( getProperty( N ) ); 00296 } 00297 00298 /** 00299 * Returns the property with the given number, but only as base type. The advantage is that the property number can be specified during 00300 * runtime. 00301 * 00302 * \param n the number of the property 00303 * 00304 * \return the property 00305 */ 00306 const WPropertyBase::SPtr& getProperty( size_t n ) const 00307 { 00308 // lock, unlocked if l looses focus 00309 PropertySharedContainerType::ReadTicket l = m_properties.getReadTicket(); 00310 return l->get()[ n ]; 00311 } 00312 00313 /** 00314 * Returns the property with the given number, but only as base type. The advantage is that the property number can be specified during 00315 * runtime. 00316 * 00317 * \param n the number of the property 00318 * 00319 * \return the property 00320 */ 00321 WPropertyBase::SPtr getProperty( size_t n ) 00322 { 00323 // lock, unlocked if l looses focus 00324 PropertySharedContainerType::ReadTicket l = m_properties.getReadTicket(); 00325 return l->get()[ n ]; 00326 } 00327 00328 /** 00329 * The size of the WPropertyStruct. This returns the number of properties encapsulated. 00330 * 00331 * \return number of properties in struct 00332 */ 00333 size_t size() const 00334 { 00335 return m_size; 00336 } 00337 00338 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00339 // The WPropertyBase specific stuff 00340 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00341 00342 /** 00343 * 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 00344 * correct type without explicitly requiring the user to specify it. It creates a NEW change condition and change signal. This means, alls 00345 * subscribed signal handlers are NOT copied. 00346 * 00347 * \note this simply ensures the copy constructor of the runtime type is issued. 00348 * 00349 * \return the deep clone of this property. 00350 */ 00351 virtual WPropertyBase::SPtr clone() 00352 { 00353 // just use the copy constructor 00354 return typename WPropertyStructType::SPtr( new WPropertyStructType( *this ) ); 00355 } 00356 00357 /** 00358 * Gets the real WPropertyVariable type of this instance. 00359 * 00360 * \return the real type. 00361 */ 00362 virtual PROPERTY_TYPE getType() const 00363 { 00364 return PV_STRUCT; 00365 } 00366 00367 /** 00368 * 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 00369 * real type of the property is unknown. This is a shortcut for casting the property and then setting the lexically casted value. 00370 * 00371 * \param value the new value to set. 00372 * 00373 * \return true if value could be set. 00374 */ 00375 virtual bool setAsString( std::string value ) 00376 { 00377 // this method splits the given string and simply forwards the call to the other properties 00378 std::vector< std::string > propsAsString = string_utils::tokenize( value, "|", false ); 00379 if( size() != propsAsString.size() ) 00380 { 00381 return false; 00382 } 00383 00384 // lock, unlocked if l looses focus 00385 PropertySharedContainerType::ReadTicket l = m_properties.getReadTicket(); 00386 // give the string to each property 00387 size_t curPropNb = 0; 00388 bool success = true; 00389 for( std::vector< std::string >::const_iterator iter = propsAsString.begin(); iter != propsAsString.end(); ++iter ) 00390 { 00391 success = success && l->get()[ curPropNb ]->setAsString( *iter ); 00392 curPropNb++; 00393 } 00394 return success; 00395 } 00396 00397 /** 00398 * Returns the current value as a string. This is useful for debugging or project files. It is not implemented as << operator, since the << 00399 * should also print min/max constraints and so on. This simply is the value. 00400 * 00401 * \return the value as a string. 00402 */ 00403 virtual std::string getAsString() 00404 { 00405 // lock, unlocked if l looses focus 00406 PropertySharedContainerType::ReadTicket l = m_properties.getReadTicket(); 00407 00408 // go through and append each prop 00409 std::string result = ""; 00410 for( size_t i = 0; i < size(); ++i ) 00411 { 00412 result += l->get()[ i ]->getAsString() + "|"; 00413 } 00414 // strip last "|" 00415 result.erase( result.length() - 1, 1 ); 00416 return result; 00417 } 00418 00419 /** 00420 * Sets the value from the specified property to this one. This is especially useful to copy a value without explicitly casting/knowing the 00421 * dynamic type of the property. 00422 * 00423 * \param value the new value. 00424 * \param recommendedOnly if true, property types which support recommended values apply the given value as recommendation. 00425 * 00426 * \return true if the value has been accepted. 00427 */ 00428 virtual bool set( boost::shared_ptr< WPropertyBase > value, bool recommendedOnly = false ) 00429 { 00430 // is this the same type as we are? 00431 typename WPropertyStructType::SPtr v = boost::dynamic_pointer_cast< WPropertyStructType >( value ); 00432 if( !v ) 00433 { 00434 // it is not a WPropertyStruct with the same type 00435 return false; 00436 } 00437 00438 // lock, unlocked if l looses focus 00439 PropertySharedContainerType::ReadTicket l = m_properties.getReadTicket(); 00440 PropertySharedContainerType::ReadTicket lother = v->m_properties.getReadTicket(); 00441 bool success = true; 00442 // set each property 00443 for( size_t curPropNb = 0; curPropNb < size(); ++curPropNb ) 00444 { 00445 success = success && l->get()[ curPropNb ]->set( lother->get()[ curPropNb ], recommendedOnly ); 00446 } 00447 00448 return success; 00449 } 00450 00451 protected: 00452 private: 00453 /** 00454 * How many elements are in this WPropertyStruct? 00455 */ 00456 static const size_t m_size = boost::mpl::size< TypeVector >::value; 00457 }; 00458 00459 #endif // WPROPERTYSTRUCT_H 00460