TuttleOFX
1
|
00001 /* 00002 * Software License : 00003 * 00004 * Copyright (c) 2007-2009, The Open Effects Association Ltd. All Rights Reserved. 00005 * 00006 * Redistribution and use in source and binary forms, with or without 00007 * modification, are permitted provided that the following conditions are met: 00008 * 00009 * Redistributions of source code must retain the above copyright notice, 00010 * this list of conditions and the following disclaimer. 00011 * Redistributions in binary form must reproduce the above copyright notice, 00012 * this list of conditions and the following disclaimer in the documentation 00013 * and/or other materials provided with the distribution. 00014 * Neither the name The Open Effects Association Ltd, nor the names of its 00015 * contributors may be used to endorse or promote products derived from this 00016 * software without specific prior written permission. 00017 * 00018 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 00019 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00020 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00021 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 00022 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 00023 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00024 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 00025 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00026 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00027 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00028 */ 00029 #ifndef _TUTTLE_HOST_OFX_PROPERTY_SET_HPP_ 00030 #define _TUTTLE_HOST_OFX_PROPERTY_SET_HPP_ 00031 00032 #include "OfxhPropertyTemplate.hpp" 00033 00034 #include <boost/ptr_container/serialize_ptr_map.hpp> 00035 00036 namespace tuttle { 00037 namespace host { 00038 namespace ofx { 00039 namespace property { 00040 00041 /// A class that is used to initialize a property set. Feed in an array of these to 00042 /// a property and it will construct a bunch of properties. Terminate such an array 00043 /// with an empty (all zero) set. 00044 struct OfxhPropSpec 00045 { 00046 const char* name; ///< name of the property 00047 EPropType type; ///< type 00048 int dimension; ///< fixed dimension of the property, set to zero if variable dimension 00049 bool readonly; ///< is the property plug-in read only 00050 const char* defaultValue; ///< Default value as a string. Pointers are ignored and always null. 00051 }; 00052 00053 /// A std::map of properties by name 00054 typedef boost::ptr_map<std::string, OfxhProperty> PropertyMap; 00055 00056 /** 00057 * Class that holds a set of properties and manipulates them 00058 * The 'fetch' methods return a property object. 00059 * The 'get' methods return a property value 00060 */ 00061 class OfxhSet 00062 { 00063 public: 00064 typedef OfxhSet This; 00065 00066 private: 00067 static const int kMagic = 0x12082007; ///< magic number for property sets, and Connie's birthday :-) 00068 const int _magic; ///< to check for handles being nice 00069 00070 protected: 00071 PropertyMap _props; ///< Our properties. 00072 00073 /// chained property set, which is read only 00074 /// these are searched on a get if not found 00075 /// on a local search 00076 const OfxhSet* _chainedSet; 00077 00078 /// set a particular property 00079 template<class T> 00080 void setProperty( const std::string& property, int index, const typename T::Type& value ); 00081 00082 /// set the first N of a particular property 00083 template<class T> 00084 void setPropertyN( const std::string& property, int count, const typename T::APIType* value ); 00085 00086 /// get a particular property 00087 template<class T> 00088 typename T::ReturnType getProperty( const std::string& property, int index ) const; 00089 00090 /// get the first N of a particular property 00091 template<class T> 00092 void getPropertyN( const std::string & property, int index, typename T::APIType * v ) const; 00093 00094 /// get a particular property without going through any getHook 00095 template<class T> 00096 typename T::ReturnType getPropertyRaw( const std::string& property, int index ) const; 00097 00098 /// get a particular property without going through any getHook 00099 template<class T> 00100 void getPropertyRawN( const std::string & property, int count, typename T::APIType * v ) const; 00101 00102 public: 00103 /// take an array of of PropSpecs (which must be terminated with an entry in which 00104 /// ->name is null), and turn these into a Set 00105 OfxhSet( const OfxhPropSpec spec[] ); 00106 // explicit Set(const std::vector<const PropSpec*>& multipleSpec); 00107 00108 /// deep copies the property set 00109 OfxhSet( const OfxhSet& ); 00110 00111 /// empty ctor 00112 OfxhSet(); 00113 00114 /// destructor 00115 virtual ~OfxhSet(); 00116 00117 void clear(); 00118 00119 size_t getLocalSize() const { return _props.size(); } 00120 size_t getSize() const 00121 { 00122 if( _chainedSet == NULL ) 00123 return getLocalSize(); 00124 else 00125 return getLocalSize() + _chainedSet->getSize(); 00126 } 00127 00128 OfxhSet& operator=( const This& ); 00129 00130 bool operator==( const This& ) const; 00131 bool operator!=( const This& other ) const { return !This::operator==( other ); } 00132 00133 void copyValues( const This& other ); 00134 00135 #ifndef SWIG 00136 friend std::ostream& operator<<( std::ostream& os, const This& g ); 00137 #endif 00138 00139 OfxhProperty& localAt( const int index ); 00140 const OfxhProperty& at( const int index ) const; 00141 00142 /// adds a bunch of properties from PropSpec 00143 void addProperties( const OfxhPropSpec* ); 00144 00145 void eraseProperty( const std::string& propName ); 00146 00147 bool hasProperty( const std::string& propName, bool followChain = true ) const; 00148 bool hasLocalProperty( const std::string& propName ) const; 00149 00150 inline OfxhSet& operator+=( const OfxhPropSpec* p ) { addProperties( p ); return *this; } 00151 00152 /// add one new property 00153 void createProperty( const OfxhPropSpec& s ); 00154 00155 /// add one new property (takes ownership) 00156 void addProperty( OfxhProperty* prop ); 00157 00158 /// set the chained property set 00159 void setChainedSet( const OfxhSet* const s ) { _chainedSet = s; } 00160 00161 const OfxhSet& getChainedSet() const { return *_chainedSet; } 00162 00163 /// grab the internal properties map 00164 const PropertyMap& getMap() const { return _props; } 00165 PropertyMap& getMap() { return _props; } 00166 00167 /// set the get hook for a particular property. users may need to call particular 00168 /// specialised versions of this. 00169 void setGetHook( const std::string& s, OfxhGetHook* ghook ); 00170 00171 /// add a set hook for a particular property. users may need to call particular 00172 /// specialised versions of this. 00173 void addNotifyHook( const std::string& name, OfxhNotifyHook* hook ); 00174 00175 /// Fetchs a reference to a property of the given name, following the property chain if the 00176 /// 'followChain' arg is not false. 00177 const OfxhProperty& fetchProperty( const std::string& name ) const; 00178 OfxhProperty& fetchLocalProperty( const std::string& name ); 00179 const OfxhProperty& fetchLocalProperty( const std::string& name ) const { return const_cast<OfxhSet*>( this )->fetchLocalProperty( name ); } 00180 00181 /// get property with the particular name and type. if the property is 00182 /// missing or is of the wrong type, return an error status. if this is a sloppy 00183 /// property set and the property is missing, a new one will be created of the right 00184 /// type 00185 template<class T> 00186 const T& fetchTypedProperty( const std::string& name ) const 00187 { 00188 return dynamic_cast<const T&>( fetchProperty( name ) ); 00189 } 00190 00191 template<class T> 00192 T& fetchLocalTypedProperty( const std::string& name ) 00193 { 00194 return dynamic_cast<T&>( fetchLocalProperty( name ) ); 00195 } 00196 00197 template<class T> 00198 const T& fetchLocalTypedProperty( const std::string& name ) const 00199 { 00200 return const_cast<OfxhSet*>( this )->fetchLocalTypedProperty<T>( name ); 00201 } 00202 00203 00204 const String& fetchStringProperty( const std::string& name ) const 00205 { 00206 return fetchTypedProperty<String>( name ); 00207 } 00208 00209 String& fetchLocalStringProperty( const std::string& name ) 00210 { 00211 return fetchLocalTypedProperty<String>( name ); 00212 } 00213 00214 const String& fetchLocalStringProperty( const std::string& name ) const { return const_cast<OfxhSet*>( this )->fetchLocalStringProperty( name ); } 00215 00216 const Int& fetchIntProperty( const std::string& name ) const 00217 { 00218 return fetchTypedProperty<Int>( name ); 00219 } 00220 00221 Int& fetchLocalIntProperty( const std::string& name ) 00222 { 00223 return fetchLocalTypedProperty<Int>( name ); 00224 } 00225 00226 const Int& fetchLocalIntProperty( const std::string& name ) const { return const_cast<OfxhSet*>( this )->fetchLocalIntProperty( name ); } 00227 00228 const Pointer& fetchPointerProperty( const std::string& name ) const 00229 { 00230 return fetchTypedProperty<Pointer>( name ); 00231 } 00232 00233 Pointer& fetchLocalPointerProperty( const std::string& name ) 00234 { 00235 return fetchLocalTypedProperty<Pointer>( name ); 00236 } 00237 00238 const Pointer& fetchLocalPointerProperty( const std::string& name ) const { return const_cast<OfxhSet*>( this )->fetchLocalPointerProperty( name ); } 00239 00240 const Double& fetchDoubleProperty( const std::string& name ) const 00241 { 00242 return fetchTypedProperty<Double>( name ); 00243 } 00244 00245 Double& fetchLocalDoubleProperty( const std::string& name ) 00246 { 00247 return fetchLocalTypedProperty<Double>( name ); 00248 } 00249 00250 const Double& fetchLocalDoubleProperty( const std::string& name ) const { return const_cast<OfxhSet*>( this )->fetchLocalDoubleProperty( name ); } 00251 00252 00253 /// get a particular int property without fetching via a get hook, useful for notifies 00254 int getIntPropertyRaw( const std::string& property, int index = 0 ) const; 00255 00256 /// get a particular double property without fetching via a get hook, useful for notifies 00257 double getDoublePropertyRaw( const std::string& property, int index = 0 ) const; 00258 00259 /// get a particular pointer property without fetching via a get hook, useful for notifies 00260 void* getPointerPropertyRaw( const std::string& property, int index = 0 ) const; /// @todo tuttle: return const no ? 00261 00262 /// get a particular string property 00263 const std::string& getStringPropertyRaw( const std::string& property, int index = 0 ) const; 00264 00265 /// get the value of a particular string property 00266 const std::string& getStringProperty( const std::string& property, int index = 0 ) const; 00267 00268 /// get the value of a particular int property 00269 int getIntProperty( const std::string& property, int index = 0 ) const; 00270 00271 /// get the value of a particular double property 00272 void getIntPropertyN( const std::string& property, int* v, int N ) const; 00273 00274 /// get the value of a particular double property 00275 double getDoubleProperty( const std::string& property, int index = 0 ) const; 00276 00277 /// get the value of a particular double property 00278 void getDoublePropertyN( const std::string& property, double* v, int N ) const; 00279 00280 /// get the value of a particular pointer property 00281 void* getPointerProperty( const std::string& property, int index = 0 ) const; 00282 00283 /// set a particular string property without fetching via a get hook, useful for notifies 00284 void setStringProperty( const std::string& property, const std::string& value, int index = 0 ) { setProperty<OfxhStringValue >( property, index, value ); } 00285 00286 /// set a particular int property 00287 void setIntProperty( const std::string& property, int v, int index = 0 ) { setProperty<OfxhIntValue >( property, index, v ); } 00288 00289 /// set a particular double property 00290 void setIntPropertyN( const std::string& property, const int* v, int N ) 00291 { 00292 setPropertyN<OfxhIntValue >( property, N, v ); 00293 } 00294 00295 /// get a particular double property 00296 void setDoubleProperty( const std::string& property, double v, int index = 0 ) { setProperty<OfxhDoubleValue >( property, index, v ); } 00297 00298 /// get a particular double property 00299 void setDoublePropertyN( const std::string& property, const double* v, int N ) { setPropertyN<OfxhDoubleValue >( property, N, v ); } 00300 00301 /// get a particular double property 00302 void setPointerProperty( const std::string& property, void* v, int index = 0 ) { setProperty<OfxhPointerValue >( property, index, v ); } 00303 00304 /// get the dimension of a particular property 00305 size_t getDimension( const std::string& property ) const { return fetchProperty( property ).getDimension(); } 00306 00307 /// is the given string one of the values of a multi-dimensional string prop 00308 /// this returns a non negative index if it is found, otherwise, -1 00309 int findStringPropValueIndex( const std::string& propName, 00310 const std::string& propValue ) const; 00311 00312 /// get a handle on this object for passing to the C API 00313 OfxPropertySetHandle getHandle() const { return ( OfxPropertySetHandle ) this; } 00314 00315 /// is this a nice property set, or a dodgy pointer passed back to us 00316 bool verifyMagic() { return this != NULL && _magic == kMagic; } 00317 00318 private: 00319 friend class boost::serialization::access; 00320 template<class Archive> 00321 void serialize( Archive& ar, const unsigned int version ) 00322 { 00323 ar& BOOST_SERIALIZATION_NVP( _props ); 00324 } 00325 00326 }; 00327 00328 /// set a particular property 00329 template<class T> 00330 void OfxhSet::setProperty( const std::string& property, int index, const typename T::Type& value ) 00331 { 00332 try 00333 { 00334 fetchLocalTypedProperty<OfxhPropertyTemplate<T> >( property ).setValue( value, index ); 00335 } 00336 catch( OfxhException& e ) 00337 { 00338 TUTTLE_LOG_ERROR( "Property::Set::setProperty - Error on " << property << " property (value=" << value << ")."); 00339 TUTTLE_LOG_ERROR( "on Property::Set (type:" << this->getStringProperty( kOfxPropType ) << ", name:" << this->getStringProperty( kOfxPropName ) << ")." ); 00340 TUTTLE_LOG_EXCEPTION( e ); 00341 //TUTTLE_LOG_DEBUG( *this ); 00342 } 00343 catch(... ) 00344 { 00345 TUTTLE_LOG_ERROR( "Property::Set::setProperty - Error on " << property << " property (value=" << value << ")." << 00346 "on Property::Set (type:" << this->getStringProperty( kOfxPropType ) << ", name:" << this->getStringProperty( kOfxPropName ) << ")." ); 00347 //TUTTLE_LOG_DEBUG( *this ); 00348 } 00349 } 00350 00351 /// set a particular property 00352 00353 template<class T> 00354 void OfxhSet::setPropertyN( const std::string& property, int count, const typename T::APIType* value ) 00355 { 00356 try 00357 { 00358 fetchLocalTypedProperty<OfxhPropertyTemplate<T> >( property ).setValueN( value, count ); 00359 } 00360 catch( OfxhException& e ) 00361 { 00362 TUTTLE_LOG_ERROR( "Set::setProperty - Error on " << property << " property (value=" << value << ")." ); 00363 TUTTLE_LOG_ERROR( "on Property::Set (type:" << this->getStringProperty( kOfxPropType ) << ", name:" << this->getStringProperty( kOfxPropName ) << ")." ); 00364 TUTTLE_LOG_EXCEPTION( e ); 00365 } 00366 catch(... ) 00367 { 00368 TUTTLE_LOG_ERROR( "Set::setProperty - Error on " << property << " property (value=" << value << ")." ); 00369 TUTTLE_LOG_ERROR( "on Property::Set (type:" << this->getStringProperty( kOfxPropType ) << ", name:" << this->getStringProperty( kOfxPropName ) << ")." ); 00370 } 00371 } 00372 00373 /// get a particular property 00374 00375 template<class T> 00376 typename T::ReturnType OfxhSet::getProperty( const std::string& property, int index ) const 00377 { 00378 /* 00379 if( !hasProperty( property, true ) ) 00380 { 00381 TUTTLE_TLOG( TUTTLE_INFO, "return kEmpty on property: " << property ); 00382 return T::kEmpty; /// @todo tuttle: is this really needed ? 00383 } 00384 */ 00385 return fetchTypedProperty<OfxhPropertyTemplate<T> >( property ).getValue( index ); 00386 } 00387 00388 /// get a particular property 00389 00390 template<class T> 00391 void OfxhSet::getPropertyN( const std::string& property, int count, typename T::APIType* value ) const 00392 { 00393 fetchTypedProperty<OfxhPropertyTemplate<T> >( property ).getValueN( value, count ); 00394 } 00395 00396 /// get a particular property 00397 00398 template<class T> 00399 typename T::ReturnType OfxhSet::getPropertyRaw( const std::string& property, int index ) const 00400 { 00401 return fetchTypedProperty<OfxhPropertyTemplate<T> >( property ).getValueRaw( index ); 00402 } 00403 00404 /// get a particular property 00405 00406 template<class T> 00407 void OfxhSet::getPropertyRawN( const std::string& property, int count, typename T::APIType* value ) const 00408 { 00409 return fetchTypedProperty<OfxhPropertyTemplate<T> >( property ).getValueNRaw( value, count ); 00410 } 00411 00412 } 00413 } 00414 } 00415 } 00416 00417 #endif