1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_cppuhelper.hxx" 26 27 #include "osl/diagnose.h" 28 #include "cppuhelper/implbase1.hxx" 29 #include "cppuhelper/weak.hxx" 30 #include "cppuhelper/propshlp.hxx" 31 #include "cppuhelper/exc_hlp.hxx" 32 #include "com/sun/star/beans/PropertyAttribute.hpp" 33 #include "com/sun/star/lang/DisposedException.hpp" 34 35 36 using namespace osl; 37 using namespace com::sun::star::uno; 38 using namespace com::sun::star::beans; 39 using namespace com::sun::star::lang; 40 using namespace rtl; 41 using namespace cppu; 42 43 namespace cppu { 44 45 IPropertyArrayHelper::~IPropertyArrayHelper() 46 { 47 } 48 49 inline const ::com::sun::star::uno::Type & getPropertyTypeIdentifier( ) SAL_THROW( () ) 50 { 51 return ::getCppuType( (Reference< XPropertyChangeListener > *)0 ); 52 } 53 inline const ::com::sun::star::uno::Type & getPropertiesTypeIdentifier() SAL_THROW( () ) 54 { 55 return ::getCppuType( (Reference< XPropertiesChangeListener > *)0 ); 56 } 57 inline const ::com::sun::star::uno::Type & getVetoableTypeIdentifier() SAL_THROW( () ) 58 { 59 return ::getCppuType( (Reference< XVetoableChangeListener > *)0 ); 60 } 61 62 extern "C" { 63 64 static int compare_OUString_Property_Impl( const void *arg1, const void *arg2 ) 65 SAL_THROW_EXTERN_C() 66 { 67 return ((OUString *)arg1)->compareTo( ((Property *)arg2)->Name ); 68 } 69 70 } 71 72 /** 73 * The class which implements the PropertySetInfo interface. 74 */ 75 76 class OPropertySetHelperInfo_Impl 77 : public WeakImplHelper1< ::com::sun::star::beans::XPropertySetInfo > 78 { 79 Sequence < Property > aInfos; 80 81 public: 82 OPropertySetHelperInfo_Impl( IPropertyArrayHelper & rHelper_ ) SAL_THROW( () ); 83 84 // XPropertySetInfo-Methoden 85 virtual Sequence< Property > SAL_CALL getProperties(void) throw(::com::sun::star::uno::RuntimeException); 86 virtual Property SAL_CALL getPropertyByName(const OUString& PropertyName) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::uno::RuntimeException); 87 virtual sal_Bool SAL_CALL hasPropertyByName(const OUString& PropertyName) throw(::com::sun::star::uno::RuntimeException); 88 }; 89 90 91 /** 92 * Create an object that implements XPropertySetInfo IPropertyArrayHelper. 93 */ 94 OPropertySetHelperInfo_Impl::OPropertySetHelperInfo_Impl( 95 IPropertyArrayHelper & rHelper_ ) 96 SAL_THROW( () ) 97 :aInfos( rHelper_.getProperties() ) 98 { 99 } 100 101 /** 102 * Return the sequence of properties, which are provided throug the constructor. 103 */ 104 Sequence< Property > OPropertySetHelperInfo_Impl::getProperties(void) throw(::com::sun::star::uno::RuntimeException) 105 106 { 107 return aInfos; 108 } 109 110 /** 111 * Return the sequence of properties, which are provided throug the constructor. 112 */ 113 Property OPropertySetHelperInfo_Impl::getPropertyByName( const OUString & PropertyName ) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::uno::RuntimeException) 114 { 115 Property * pR; 116 pR = (Property *)bsearch( &PropertyName, aInfos.getConstArray(), aInfos.getLength(), 117 sizeof( Property ), 118 compare_OUString_Property_Impl ); 119 if( !pR ) { 120 throw UnknownPropertyException(); 121 } 122 123 return *pR; 124 } 125 126 /** 127 * Return the sequence of properties, which are provided throug the constructor. 128 */ 129 sal_Bool OPropertySetHelperInfo_Impl::hasPropertyByName( const OUString & PropertyName ) throw(::com::sun::star::uno::RuntimeException) 130 { 131 Property * pR; 132 pR = (Property *)bsearch( &PropertyName, aInfos.getConstArray(), aInfos.getLength(), 133 sizeof( Property ), 134 compare_OUString_Property_Impl ); 135 return pR != NULL; 136 } 137 138 // ---------------------------------------------------- 139 // class PropertySetHelper_Impl 140 // ---------------------------------------------------- 141 class OPropertySetHelper::Impl { 142 143 public: 144 Impl( bool i_bIgnoreRuntimeExceptionsWhileFiring, 145 IEventNotificationHook *i_pFireEvents 146 ) 147 :m_bIgnoreRuntimeExceptionsWhileFiring( i_bIgnoreRuntimeExceptionsWhileFiring ) 148 ,m_pFireEvents( i_pFireEvents ) 149 { 150 } 151 152 bool m_bIgnoreRuntimeExceptionsWhileFiring; 153 class IEventNotificationHook * const m_pFireEvents; 154 155 ::std::vector< sal_Int32 > m_handles; 156 ::std::vector< Any > m_newValues; 157 ::std::vector< Any > m_oldValues; 158 }; 159 160 161 // ---------------------------------------------------- 162 // class PropertySetHelper 163 // ---------------------------------------------------- 164 OPropertySetHelper::OPropertySetHelper( 165 OBroadcastHelper & rBHelper_ ) SAL_THROW( () ) 166 : rBHelper( rBHelper_ ), 167 aBoundLC( rBHelper_.rMutex ), 168 aVetoableLC( rBHelper_.rMutex ), 169 m_pReserved( new Impl(false, 0) ) 170 { 171 } 172 173 OPropertySetHelper::OPropertySetHelper( 174 OBroadcastHelper & rBHelper_, bool bIgnoreRuntimeExceptionsWhileFiring ) 175 : rBHelper( rBHelper_ ), 176 aBoundLC( rBHelper_.rMutex ), 177 aVetoableLC( rBHelper_.rMutex ), 178 m_pReserved( new Impl( bIgnoreRuntimeExceptionsWhileFiring, 0 ) ) 179 { 180 } 181 182 OPropertySetHelper::OPropertySetHelper( 183 OBroadcastHelper & rBHelper_, IEventNotificationHook * i_pFireEvents, 184 bool bIgnoreRuntimeExceptionsWhileFiring) 185 : rBHelper( rBHelper_ ), 186 aBoundLC( rBHelper_.rMutex ), 187 aVetoableLC( rBHelper_.rMutex ), 188 m_pReserved( 189 new Impl( bIgnoreRuntimeExceptionsWhileFiring, i_pFireEvents) ) 190 { 191 } 192 193 /** 194 * You must call disposing before. 195 */ 196 OPropertySetHelper::~OPropertySetHelper() SAL_THROW( () ) 197 { 198 } 199 200 /** 201 * These method is called from queryInterface, if no delegator is set. 202 * Otherwise this method is called from the delegator. 203 */ 204 // XAggregation 205 Any OPropertySetHelper::queryInterface( const ::com::sun::star::uno::Type & rType ) 206 throw (RuntimeException) 207 { 208 return ::cppu::queryInterface( 209 rType, 210 static_cast< XPropertySet * >( this ), 211 static_cast< XMultiPropertySet * >( this ), 212 static_cast< XFastPropertySet * >( this ) ); 213 } 214 215 /** 216 * called from the derivee's XTypeProvider::getTypes implementation 217 */ 218 ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > OPropertySetHelper::getTypes() 219 throw (RuntimeException) 220 { 221 Sequence< ::com::sun::star::uno::Type > aTypes( 3 ); 222 aTypes[ 0 ] = XPropertySet::static_type(); 223 aTypes[ 1 ] = XMultiPropertySet::static_type(); 224 aTypes[ 2 ] = XFastPropertySet::static_type(); 225 return aTypes; 226 } 227 228 // ComponentHelper 229 void OPropertySetHelper::disposing() SAL_THROW( () ) 230 { 231 // Create an event with this as sender 232 Reference < XPropertySet > rSource( SAL_STATIC_CAST( XPropertySet * , this ) , UNO_QUERY ); 233 EventObject aEvt; 234 aEvt.Source = rSource; 235 236 // inform all listeners to reelease this object 237 // The listener container are automaticly cleared 238 aBoundLC.disposeAndClear( aEvt ); 239 aVetoableLC.disposeAndClear( aEvt ); 240 } 241 242 Reference < XPropertySetInfo > OPropertySetHelper::createPropertySetInfo( 243 IPropertyArrayHelper & rProperties ) SAL_THROW( () ) 244 { 245 return static_cast< XPropertySetInfo * >( new OPropertySetHelperInfo_Impl( rProperties ) ); 246 } 247 248 // XPropertySet 249 void OPropertySetHelper::setPropertyValue( 250 const OUString& rPropertyName, const Any& rValue ) 251 throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::beans::PropertyVetoException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException) 252 { 253 // get the map table 254 IPropertyArrayHelper & rPH = getInfoHelper(); 255 // map the name to the handle 256 sal_Int32 nHandle = rPH.getHandleByName( rPropertyName ); 257 // call the method of the XFastPropertySet interface 258 setFastPropertyValue( nHandle, rValue ); 259 } 260 261 // XPropertySet 262 Any OPropertySetHelper::getPropertyValue( 263 const OUString& rPropertyName ) 264 throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException) 265 { 266 // get the map table 267 IPropertyArrayHelper & rPH = getInfoHelper(); 268 // map the name to the handle 269 sal_Int32 nHandle = rPH.getHandleByName( rPropertyName ); 270 // call the method of the XFastPropertySet interface 271 return getFastPropertyValue( nHandle ); 272 } 273 274 // XPropertySet 275 void OPropertySetHelper::addPropertyChangeListener( 276 const OUString& rPropertyName, 277 const Reference < XPropertyChangeListener > & rxListener ) 278 throw(::com::sun::star::beans::UnknownPropertyException, 279 ::com::sun::star::lang::WrappedTargetException, 280 ::com::sun::star::uno::RuntimeException) 281 { 282 MutexGuard aGuard( rBHelper.rMutex ); 283 OSL_ENSURE( !rBHelper.bInDispose, "do not addPropertyChangeListener in the dispose call" ); 284 OSL_ENSURE( !rBHelper.bDisposed, "object is disposed" ); 285 if( !rBHelper.bInDispose && !rBHelper.bDisposed ) 286 { 287 // only add listeners if you are not disposed 288 // a listener with no name means all properties 289 if( rPropertyName.getLength() ) 290 { 291 // get the map table 292 IPropertyArrayHelper & rPH = getInfoHelper(); 293 // map the name to the handle 294 sal_Int32 nHandle = rPH.getHandleByName( rPropertyName ); 295 if( nHandle == -1 ) { 296 // property not known throw exception 297 throw UnknownPropertyException() ; 298 } 299 300 sal_Int16 nAttributes; 301 rPH.fillPropertyMembersByHandle( NULL, &nAttributes, nHandle ); 302 if( !(nAttributes & ::com::sun::star::beans::PropertyAttribute::BOUND) ) 303 { 304 OSL_ENSURE( sal_False, "add listener to an unbound property" ); 305 // silent ignore this 306 return; 307 } 308 // add the change listener to the helper container 309 310 aBoundLC.addInterface( (sal_Int32)nHandle, rxListener ); 311 } 312 else 313 // add the change listener to the helper container 314 rBHelper.aLC.addInterface( 315 getPropertyTypeIdentifier( ), 316 rxListener 317 ); 318 } 319 } 320 321 322 // XPropertySet 323 void OPropertySetHelper::removePropertyChangeListener( 324 const OUString& rPropertyName, 325 const Reference < XPropertyChangeListener >& rxListener ) 326 throw(::com::sun::star::beans::UnknownPropertyException, 327 ::com::sun::star::lang::WrappedTargetException, 328 ::com::sun::star::uno::RuntimeException) 329 { 330 MutexGuard aGuard( rBHelper.rMutex ); 331 OSL_ENSURE( !rBHelper.bDisposed, "object is disposed" ); 332 // all listeners are automaticly released in a dispose call 333 if( !rBHelper.bInDispose && !rBHelper.bDisposed ) 334 { 335 if( rPropertyName.getLength() ) 336 { 337 // get the map table 338 IPropertyArrayHelper & rPH = getInfoHelper(); 339 // map the name to the handle 340 sal_Int32 nHandle = rPH.getHandleByName( rPropertyName ); 341 if( nHandle == -1 ) 342 // property not known throw exception 343 throw UnknownPropertyException(); 344 aBoundLC.removeInterface( (sal_Int32)nHandle, rxListener ); 345 } 346 else { 347 // remove the change listener to the helper container 348 rBHelper.aLC.removeInterface( 349 getPropertyTypeIdentifier( ), 350 rxListener 351 ); 352 } 353 } 354 } 355 356 // XPropertySet 357 void OPropertySetHelper::addVetoableChangeListener( 358 const OUString& rPropertyName, 359 const Reference< XVetoableChangeListener > & rxListener ) 360 throw(::com::sun::star::beans::UnknownPropertyException, 361 ::com::sun::star::lang::WrappedTargetException, 362 ::com::sun::star::uno::RuntimeException) 363 { 364 MutexGuard aGuard( rBHelper.rMutex ); 365 OSL_ENSURE( !rBHelper.bInDispose, "do not addVetoableChangeListener in the dispose call" ); 366 OSL_ENSURE( !rBHelper.bDisposed, "object is disposed" ); 367 if( !rBHelper.bInDispose && !rBHelper.bDisposed ) 368 { 369 // only add listeners if you are not disposed 370 // a listener with no name means all properties 371 if( rPropertyName.getLength() ) 372 { 373 // get the map table 374 IPropertyArrayHelper & rPH = getInfoHelper(); 375 // map the name to the handle 376 sal_Int32 nHandle = rPH.getHandleByName( rPropertyName ); 377 if( nHandle == -1 ) { 378 // property not known throw exception 379 throw UnknownPropertyException(); 380 } 381 382 sal_Int16 nAttributes; 383 rPH.fillPropertyMembersByHandle( NULL, &nAttributes, nHandle ); 384 if( !(nAttributes & PropertyAttribute::CONSTRAINED) ) 385 { 386 OSL_ENSURE( sal_False, "addVetoableChangeListener, and property is not constrained" ); 387 // silent ignore this 388 return; 389 } 390 // add the vetoable listener to the helper container 391 aVetoableLC.addInterface( (sal_Int32)nHandle, rxListener ); 392 } 393 else 394 // add the vetoable listener to the helper container 395 rBHelper.aLC.addInterface( 396 getVetoableTypeIdentifier( ), 397 rxListener 398 ); 399 } 400 } 401 402 // XPropertySet 403 void OPropertySetHelper::removeVetoableChangeListener( 404 const OUString& rPropertyName, 405 const Reference < XVetoableChangeListener > & rxListener ) 406 throw(::com::sun::star::beans::UnknownPropertyException, 407 ::com::sun::star::lang::WrappedTargetException, 408 ::com::sun::star::uno::RuntimeException) 409 { 410 MutexGuard aGuard( rBHelper.rMutex ); 411 OSL_ENSURE( !rBHelper.bDisposed, "object is disposed" ); 412 // all listeners are automaticly released in a dispose call 413 if( !rBHelper.bInDispose && !rBHelper.bDisposed ) 414 { 415 if( rPropertyName.getLength() ) 416 { 417 // get the map table 418 IPropertyArrayHelper & rPH = getInfoHelper(); 419 // map the name to the handle 420 sal_Int32 nHandle = rPH.getHandleByName( rPropertyName ); 421 if( nHandle == -1 ) { 422 // property not known throw exception 423 throw UnknownPropertyException(); 424 } 425 // remove the vetoable listener to the helper container 426 aVetoableLC.removeInterface( (sal_Int32)nHandle, rxListener ); 427 } 428 else 429 // add the vetoable listener to the helper container 430 rBHelper.aLC.removeInterface( 431 getVetoableTypeIdentifier( ), 432 rxListener 433 ); 434 } 435 } 436 437 void OPropertySetHelper::setDependentFastPropertyValue( sal_Int32 i_handle, const ::com::sun::star::uno::Any& i_value ) 438 { 439 //OSL_PRECOND( rBHelper.rMutex.isAcquired(), "OPropertySetHelper::setDependentFastPropertyValue: to be called with a locked mutex only!" ); 440 // there is no such thing as Mutex.isAcquired, sadly ... 441 442 sal_Int16 nAttributes(0); 443 IPropertyArrayHelper& rInfo = getInfoHelper(); 444 if ( !rInfo.fillPropertyMembersByHandle( NULL, &nAttributes, i_handle ) ) 445 // unknown property 446 throw UnknownPropertyException(); 447 448 // no need to check for READONLY-ness of the property. The method is intended to be called internally, which 449 // implies it might be invoked for properties which are read-only to the instance's clients, but well allowed 450 // to change their value. 451 452 Any aConverted, aOld; 453 sal_Bool bChanged = convertFastPropertyValue( aConverted, aOld, i_handle, i_value ); 454 if ( !bChanged ) 455 return; 456 457 // don't fire vetoable events. This method is called with our mutex locked, so calling into listeners would not be 458 // a good idea. The caler is responsible for not invoking this for constrained properties. 459 OSL_ENSURE( ( nAttributes & PropertyAttribute::CONSTRAINED ) == 0, 460 "OPropertySetHelper::setDependentFastPropertyValue: not to be used for constrained properties!" ); 461 (void)nAttributes; 462 463 // actually set the new value 464 try 465 { 466 setFastPropertyValue_NoBroadcast( i_handle, aConverted ); 467 } 468 catch (const UnknownPropertyException& ) { throw; /* allowed to leave */ } 469 catch (const PropertyVetoException& ) { throw; /* allowed to leave */ } 470 catch (const IllegalArgumentException& ) { throw; /* allowed to leave */ } 471 catch (const WrappedTargetException& ) { throw; /* allowed to leave */ } 472 catch (const RuntimeException& ) { throw; /* allowed to leave */ } 473 catch (const Exception& ) 474 { 475 // not allowed to leave this meathod 476 WrappedTargetException aWrapped; 477 aWrapped.TargetException <<= ::cppu::getCaughtException(); 478 aWrapped.Context = static_cast< XPropertySet* >( this ); 479 throw aWrapped; 480 } 481 482 // remember the handle/values, for the events to be fired later 483 m_pReserved->m_handles.push_back( i_handle ); 484 m_pReserved->m_newValues.push_back( aConverted ); // TODO: setFastPropertyValue notifies the unconverted value here ...? 485 m_pReserved->m_oldValues.push_back( aOld ); 486 } 487 488 // XFastPropertySet 489 void OPropertySetHelper::setFastPropertyValue( sal_Int32 nHandle, const Any& rValue ) 490 throw(::com::sun::star::beans::UnknownPropertyException, 491 ::com::sun::star::beans::PropertyVetoException, 492 ::com::sun::star::lang::IllegalArgumentException, 493 ::com::sun::star::lang::WrappedTargetException, 494 ::com::sun::star::uno::RuntimeException) 495 { 496 OSL_ENSURE( !rBHelper.bInDispose, "do not setFastPropertyValue in the dispose call" ); 497 OSL_ENSURE( !rBHelper.bDisposed, "object is disposed" ); 498 499 IPropertyArrayHelper & rInfo = getInfoHelper(); 500 sal_Int16 nAttributes; 501 if( !rInfo.fillPropertyMembersByHandle( NULL, &nAttributes, nHandle ) ) { 502 // unknown property 503 throw UnknownPropertyException(); 504 } 505 if( nAttributes & PropertyAttribute::READONLY ) 506 throw PropertyVetoException(); 507 508 Any aConvertedVal; 509 Any aOldVal; 510 511 // Will the property change? 512 sal_Bool bChanged; 513 { 514 MutexGuard aGuard( rBHelper.rMutex ); 515 bChanged = convertFastPropertyValue( aConvertedVal, aOldVal, nHandle, rValue ); 516 // release guard to fire events 517 } 518 if( bChanged ) 519 { 520 // Is it a constrained property? 521 if( nAttributes & PropertyAttribute::CONSTRAINED ) 522 { 523 // In aValue is the converted rValue 524 // fire a constarined event 525 // second parameter NULL means constrained 526 fire( &nHandle, &rValue, &aOldVal, 1, sal_True ); 527 } 528 529 { 530 MutexGuard aGuard( rBHelper.rMutex ); 531 try 532 { 533 // set the property to the new value 534 setFastPropertyValue_NoBroadcast( nHandle, aConvertedVal ); 535 } 536 catch (const ::com::sun::star::beans::UnknownPropertyException& ) { throw; /* allowed to leave */ } 537 catch (const ::com::sun::star::beans::PropertyVetoException& ) { throw; /* allowed to leave */ } 538 catch (const ::com::sun::star::lang::IllegalArgumentException& ) { throw; /* allowed to leave */ } 539 catch (const ::com::sun::star::lang::WrappedTargetException& ) { throw; /* allowed to leave */ } 540 catch (const ::com::sun::star::uno::RuntimeException& ) { throw; /* allowed to leave */ } 541 catch (const ::com::sun::star::uno::Exception& e ) 542 { 543 // not allowed to leave this meathod 544 ::com::sun::star::lang::WrappedTargetException aWrap; 545 aWrap.Context = static_cast< ::com::sun::star::beans::XPropertySet* >( this ); 546 aWrap.TargetException <<= e; 547 548 throw ::com::sun::star::lang::WrappedTargetException( aWrap ); 549 } 550 551 // release guard to fire events 552 } 553 // file a change event, if the value changed 554 impl_fireAll( &nHandle, &rValue, &aOldVal, 1 ); 555 } 556 } 557 558 // XFastPropertySet 559 Any OPropertySetHelper::getFastPropertyValue( sal_Int32 nHandle ) 560 throw(::com::sun::star::beans::UnknownPropertyException, 561 ::com::sun::star::lang::WrappedTargetException, 562 ::com::sun::star::uno::RuntimeException) 563 564 { 565 IPropertyArrayHelper & rInfo = getInfoHelper(); 566 if( !rInfo.fillPropertyMembersByHandle( NULL, NULL, nHandle ) ) 567 // unknown property 568 throw UnknownPropertyException(); 569 570 Any aRet; 571 MutexGuard aGuard( rBHelper.rMutex ); 572 getFastPropertyValue( aRet, nHandle ); 573 return aRet; 574 } 575 576 //-------------------------------------------------------------------------- 577 void OPropertySetHelper::impl_fireAll( sal_Int32* i_handles, const Any* i_newValues, const Any* i_oldValues, sal_Int32 i_count ) 578 { 579 ClearableMutexGuard aGuard( rBHelper.rMutex ); 580 if ( m_pReserved->m_handles.empty() ) 581 { 582 aGuard.clear(); 583 fire( i_handles, i_newValues, i_oldValues, i_count, sal_False ); 584 return; 585 } 586 587 const size_t additionalEvents = m_pReserved->m_handles.size(); 588 OSL_ENSURE( additionalEvents == m_pReserved->m_newValues.size() 589 && additionalEvents == m_pReserved->m_oldValues.size(), 590 "OPropertySetHelper::impl_fireAll: inconsistency!" ); 591 592 ::std::vector< sal_Int32 > allHandles( additionalEvents + i_count ); 593 ::std::copy( m_pReserved->m_handles.begin(), m_pReserved->m_handles.end(), allHandles.begin() ); 594 ::std::copy( i_handles, i_handles + i_count, allHandles.begin() + additionalEvents ); 595 596 ::std::vector< Any > allNewValues( additionalEvents + i_count ); 597 ::std::copy( m_pReserved->m_newValues.begin(), m_pReserved->m_newValues.end(), allNewValues.begin() ); 598 ::std::copy( i_newValues, i_newValues + i_count, allNewValues.begin() + additionalEvents ); 599 600 ::std::vector< Any > allOldValues( additionalEvents + i_count ); 601 ::std::copy( m_pReserved->m_oldValues.begin(), m_pReserved->m_oldValues.end(), allOldValues.begin() ); 602 ::std::copy( i_oldValues, i_oldValues + i_count, allOldValues.begin() + additionalEvents ); 603 604 m_pReserved->m_handles.clear(); 605 m_pReserved->m_newValues.clear(); 606 m_pReserved->m_oldValues.clear(); 607 608 aGuard.clear(); 609 fire( &allHandles[0], &allNewValues[0], &allOldValues[0], additionalEvents + i_count, sal_False ); 610 } 611 612 //-------------------------------------------------------------------------- 613 void OPropertySetHelper::fire 614 ( 615 sal_Int32 * pnHandles, 616 const Any * pNewValues, 617 const Any * pOldValues, 618 sal_Int32 nHandles, // These is the Count of the array 619 sal_Bool bVetoable 620 ) 621 { 622 OSL_ENSURE( m_pReserved.get(), "No OPropertySetHelper::Impl" ); 623 if (m_pReserved->m_pFireEvents) { 624 m_pReserved->m_pFireEvents->fireEvents( 625 pnHandles, nHandles, bVetoable, 626 m_pReserved->m_bIgnoreRuntimeExceptionsWhileFiring); 627 } 628 629 // Only fire, if one or more properties changed 630 if( nHandles ) 631 { 632 // create the event sequence of all changed properties 633 Sequence< PropertyChangeEvent > aEvts( nHandles ); 634 PropertyChangeEvent * pEvts = aEvts.getArray(); 635 Reference < XInterface > xSource( (XPropertySet *)this, UNO_QUERY ); 636 sal_Int32 i; 637 sal_Int32 nChangesLen = 0; 638 // Loop over all changed properties to fill the event struct 639 for( i = 0; i < nHandles; i++ ) 640 { 641 // Vetoable fire and constrained attribute set or 642 // Change fire and Changed and bound attribute set 643 IPropertyArrayHelper & rInfo = getInfoHelper(); 644 sal_Int16 nAttributes; 645 OUString aPropName; 646 rInfo.fillPropertyMembersByHandle( &aPropName, &nAttributes, pnHandles[i] ); 647 648 if( 649 (bVetoable && (nAttributes & PropertyAttribute::CONSTRAINED)) || 650 (!bVetoable && (nAttributes & PropertyAttribute::BOUND)) 651 ) 652 { 653 pEvts[nChangesLen].Source = xSource; 654 pEvts[nChangesLen].PropertyName = aPropName; 655 pEvts[nChangesLen].PropertyHandle = pnHandles[i]; 656 pEvts[nChangesLen].OldValue = pOldValues[i]; 657 pEvts[nChangesLen].NewValue = pNewValues[i]; 658 nChangesLen++; 659 } 660 } 661 662 bool bIgnoreRuntimeExceptionsWhileFiring = 663 m_pReserved->m_bIgnoreRuntimeExceptionsWhileFiring; 664 665 // fire the events for all changed properties 666 for( i = 0; i < nChangesLen; i++ ) 667 { 668 // get the listener container for the property name 669 OInterfaceContainerHelper * pLC; 670 if( bVetoable ) // fire change Events? 671 pLC = aVetoableLC.getContainer( pEvts[i].PropertyHandle ); 672 else 673 pLC = aBoundLC.getContainer( pEvts[i].PropertyHandle ); 674 if( pLC ) 675 { 676 // Ueber alle Listener iterieren und Events senden 677 OInterfaceIteratorHelper aIt( *pLC); 678 while( aIt.hasMoreElements() ) 679 { 680 XInterface * pL = aIt.next(); 681 try 682 { 683 try 684 { 685 if( bVetoable ) // fire change Events? 686 { 687 ((XVetoableChangeListener *)pL)->vetoableChange( 688 pEvts[i] ); 689 } 690 else 691 { 692 ((XPropertyChangeListener *)pL)->propertyChange( 693 pEvts[i] ); 694 } 695 } 696 catch (DisposedException & exc) 697 { 698 OSL_ENSURE( exc.Context.is(), 699 "DisposedException without Context!" ); 700 if (exc.Context == pL) 701 aIt.remove(); 702 else 703 throw; 704 } 705 } 706 catch (RuntimeException & exc) 707 { 708 OSL_TRACE( 709 OUStringToOString( 710 OUString( RTL_CONSTASCII_USTRINGPARAM( 711 "caught RuntimeException while " 712 "firing listeners: ") ) + 713 exc.Message, RTL_TEXTENCODING_UTF8 ).getStr() ); 714 if (! bIgnoreRuntimeExceptionsWhileFiring) 715 throw; 716 } 717 } 718 } 719 // broadcast to all listeners with "" property name 720 if( bVetoable ){ 721 // fire change Events? 722 pLC = rBHelper.aLC.getContainer( 723 getVetoableTypeIdentifier() 724 ); 725 } 726 else { 727 pLC = rBHelper.aLC.getContainer( 728 getPropertyTypeIdentifier( ) 729 ); 730 } 731 if( pLC ) 732 { 733 // Ueber alle Listener iterieren und Events senden 734 OInterfaceIteratorHelper aIt( *pLC); 735 while( aIt.hasMoreElements() ) 736 { 737 XInterface * pL = aIt.next(); 738 try 739 { 740 try 741 { 742 if( bVetoable ) // fire change Events? 743 { 744 ((XVetoableChangeListener *)pL)->vetoableChange( 745 pEvts[i] ); 746 } 747 else 748 { 749 ((XPropertyChangeListener *)pL)->propertyChange( 750 pEvts[i] ); 751 } 752 } 753 catch (DisposedException & exc) 754 { 755 OSL_ENSURE( exc.Context.is(), 756 "DisposedException without Context!" ); 757 if (exc.Context == pL) 758 aIt.remove(); 759 else 760 throw; 761 } 762 } 763 catch (RuntimeException & exc) 764 { 765 OSL_TRACE( 766 OUStringToOString( 767 OUString( RTL_CONSTASCII_USTRINGPARAM( 768 "caught RuntimeException while " 769 "firing listeners: ") ) + 770 exc.Message, RTL_TEXTENCODING_UTF8 ).getStr() ); 771 if (! bIgnoreRuntimeExceptionsWhileFiring) 772 throw; 773 } 774 } 775 } 776 } 777 778 // reduce array to changed properties 779 aEvts.realloc( nChangesLen ); 780 781 if( !bVetoable ) 782 { 783 OInterfaceContainerHelper * pCont = 0; 784 pCont = rBHelper.aLC.getContainer( 785 getPropertiesTypeIdentifier( ) 786 ); 787 if( pCont ) 788 { 789 // Here is a Bug, unbound properties are also fired 790 OInterfaceIteratorHelper aIt( *pCont ); 791 while( aIt.hasMoreElements() ) 792 { 793 XPropertiesChangeListener * pL = 794 (XPropertiesChangeListener *)aIt.next(); 795 try 796 { 797 try 798 { 799 // fire the hole event sequence to the 800 // XPropertiesChangeListener's 801 pL->propertiesChange( aEvts ); 802 } 803 catch (DisposedException & exc) 804 { 805 OSL_ENSURE( exc.Context.is(), 806 "DisposedException without Context!" ); 807 if (exc.Context == pL) 808 aIt.remove(); 809 else 810 throw; 811 } 812 } 813 catch (RuntimeException & exc) 814 { 815 OSL_TRACE( 816 OUStringToOString( 817 OUString( RTL_CONSTASCII_USTRINGPARAM( 818 "caught RuntimeException while " 819 "firing listeners: ") ) + 820 exc.Message, RTL_TEXTENCODING_UTF8 ).getStr() ); 821 if (! bIgnoreRuntimeExceptionsWhileFiring) 822 throw; 823 } 824 } 825 } 826 } 827 } 828 } 829 830 // OPropertySetHelper 831 void OPropertySetHelper::setFastPropertyValues( 832 sal_Int32 nSeqLen, 833 sal_Int32 * pHandles, 834 const Any * pValues, 835 sal_Int32 nHitCount ) 836 SAL_THROW( (::com::sun::star::uno::Exception) ) 837 { 838 OSL_ENSURE( !rBHelper.bInDispose, "do not getFastPropertyValue in the dispose call" ); 839 OSL_ENSURE( !rBHelper.bDisposed, "object is disposed" ); 840 841 Any * pConvertedValues = NULL; 842 Any * pOldValues = NULL; 843 844 try 845 { 846 // get the map table 847 IPropertyArrayHelper & rPH = getInfoHelper(); 848 849 pConvertedValues = new Any[ nHitCount ]; 850 pOldValues = new Any[ nHitCount ]; 851 sal_Int32 n = 0; 852 sal_Int32 i; 853 854 { 855 // must lock the mutex outside the loop. So all values are consistent. 856 MutexGuard aGuard( rBHelper.rMutex ); 857 for( i = 0; i < nSeqLen; i++ ) 858 { 859 if( pHandles[i] != -1 ) 860 { 861 sal_Int16 nAttributes; 862 rPH.fillPropertyMembersByHandle( NULL, &nAttributes, pHandles[i] ); 863 if( nAttributes & PropertyAttribute::READONLY ) { 864 throw PropertyVetoException(); 865 } 866 // Will the property change? 867 if( convertFastPropertyValue( pConvertedValues[ n ], pOldValues[n], 868 pHandles[i], pValues[i] ) ) 869 { 870 // only increment if the property really change 871 pHandles[n] = pHandles[i]; 872 n++; 873 } 874 } 875 } 876 // release guard to fire events 877 } 878 879 // fire vetoable events 880 fire( pHandles, pConvertedValues, pOldValues, n, sal_True ); 881 882 { 883 // must lock the mutex outside the loop. 884 MutexGuard aGuard( rBHelper.rMutex ); 885 // Loop over all changed properties 886 for( i = 0; i < n; i++ ) 887 { 888 // Will the property change? 889 setFastPropertyValue_NoBroadcast( pHandles[i], pConvertedValues[i] ); 890 } 891 // release guard to fire events 892 } 893 894 // fire change events 895 impl_fireAll( pHandles, pConvertedValues, pOldValues, n ); 896 } 897 catch( ... ) 898 { 899 delete [] pOldValues; 900 delete [] pConvertedValues; 901 throw; 902 } 903 delete [] pOldValues; 904 delete [] pConvertedValues; 905 } 906 907 // XMultiPropertySet 908 /** 909 * The sequence may be conatain not known properties. The implementation 910 * must ignore these properties. 911 */ 912 void OPropertySetHelper::setPropertyValues( 913 const Sequence<OUString>& rPropertyNames, 914 const Sequence<Any>& rValues ) 915 throw(::com::sun::star::beans::PropertyVetoException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException) 916 { 917 sal_Int32 * pHandles = NULL; 918 try 919 { 920 sal_Int32 nSeqLen = rPropertyNames.getLength(); 921 pHandles = new sal_Int32[ nSeqLen ]; 922 // get the map table 923 IPropertyArrayHelper & rPH = getInfoHelper(); 924 // fill the handle array 925 sal_Int32 nHitCount = rPH.fillHandles( pHandles, rPropertyNames ); 926 if( nHitCount != 0 ) 927 setFastPropertyValues( nSeqLen, pHandles, rValues.getConstArray(), nHitCount ); 928 } 929 catch( ... ) 930 { 931 delete [] pHandles; 932 throw; 933 } 934 delete [] pHandles; 935 } 936 937 // XMultiPropertySet 938 Sequence<Any> OPropertySetHelper::getPropertyValues( const Sequence<OUString>& rPropertyNames ) 939 throw(::com::sun::star::uno::RuntimeException) 940 { 941 sal_Int32 nSeqLen = rPropertyNames.getLength(); 942 sal_Int32 * pHandles = new sal_Int32[ nSeqLen ]; 943 Sequence< Any > aValues( nSeqLen ); 944 945 // get the map table 946 IPropertyArrayHelper & rPH = getInfoHelper(); 947 // fill the handle array 948 rPH.fillHandles( pHandles, rPropertyNames ); 949 950 Any * pValues = aValues.getArray(); 951 952 MutexGuard aGuard( rBHelper.rMutex ); 953 // fill the sequence with the values 954 for( sal_Int32 i = 0; i < nSeqLen; i++ ) 955 getFastPropertyValue( pValues[i], pHandles[i] ); 956 957 delete [] pHandles; 958 return aValues; 959 } 960 961 // XMultiPropertySet 962 void OPropertySetHelper::addPropertiesChangeListener( 963 const Sequence<OUString> & , 964 const Reference < XPropertiesChangeListener > & rListener ) 965 throw(::com::sun::star::uno::RuntimeException) 966 { 967 rBHelper.addListener( getCppuType(&rListener) , rListener ); 968 } 969 970 // XMultiPropertySet 971 void OPropertySetHelper::removePropertiesChangeListener( 972 const Reference < XPropertiesChangeListener > & rListener ) 973 throw(::com::sun::star::uno::RuntimeException) 974 { 975 rBHelper.removeListener( getCppuType(&rListener) , rListener ); 976 } 977 978 // XMultiPropertySet 979 void OPropertySetHelper::firePropertiesChangeEvent( 980 const Sequence<OUString>& rPropertyNames, 981 const Reference < XPropertiesChangeListener >& rListener ) 982 throw(::com::sun::star::uno::RuntimeException) 983 { 984 sal_Int32 nLen = rPropertyNames.getLength(); 985 sal_Int32 * pHandles = new sal_Int32[nLen]; 986 IPropertyArrayHelper & rPH = getInfoHelper(); 987 rPH.fillHandles( pHandles, rPropertyNames ); 988 const OUString* pNames = rPropertyNames.getConstArray(); 989 990 // get the count of matching properties 991 sal_Int32 nFireLen = 0; 992 sal_Int32 i; 993 for( i = 0; i < nLen; i++ ) 994 if( pHandles[i] != -1 ) 995 nFireLen++; 996 997 Sequence<PropertyChangeEvent> aChanges( nFireLen ); 998 PropertyChangeEvent* pChanges = aChanges.getArray(); 999 1000 sal_Int32 nFirePos = 0; 1001 { 1002 // must lock the mutex outside the loop. So all values are consistent. 1003 MutexGuard aGuard( rBHelper.rMutex ); 1004 Reference < XInterface > xSource( (XPropertySet *)this, UNO_QUERY ); 1005 for( i = 0; i < nLen; i++ ) 1006 { 1007 if( pHandles[i] != -1 ) 1008 { 1009 pChanges[nFirePos].Source = xSource; 1010 pChanges[nFirePos].PropertyName = pNames[i]; 1011 pChanges[nFirePos].PropertyHandle = pHandles[i]; 1012 getFastPropertyValue( pChanges[nFirePos].OldValue, pHandles[i] ); 1013 pChanges[nFirePos].NewValue = pChanges[nFirePos].OldValue; 1014 nFirePos++; 1015 } 1016 } 1017 // release guard to fire events 1018 } 1019 if( nFireLen ) 1020 rListener->propertiesChange( aChanges ); 1021 1022 delete [] pHandles; 1023 } 1024 1025 #ifdef xdvnsdfln 1026 // XPropertyState 1027 PropertyState OPropertySetHelper::getPropertyState( const OUString& PropertyName ) 1028 { 1029 PropertyState aState; 1030 return aState; 1031 } 1032 1033 // XPropertyState 1034 Sequence< PropertyState > OPropertySetHelper::getPropertyStates( const Sequence< OUString >& PropertyNames ) 1035 { 1036 ULONG nNames = PropertyNames.getLength(); 1037 const OUString* pNames = PropertyNames.getConstArray(); 1038 1039 Sequence< PropertyState > aStates( nNames ); 1040 return aStates; 1041 1042 } 1043 1044 void OPropertySetHelper::setPropertyToDefault( const OUString& aPropertyName ) 1045 { 1046 setPropertyValue( aPropertyName, Any() ); 1047 } 1048 1049 Any OPropertySetHelper::getPropertyDefault( const OUString& aPropertyName ) const 1050 { 1051 return Any(); 1052 } 1053 1054 void OPropertySetHelper::addPropertyStateChangeListener( const OUString& aPropertyName, const XPropertyStateChangeListenerRef& Listener ) 1055 { 1056 } 1057 1058 void OPropertySetHelper::removePropertyStateChangeListener( const OUString& aPropertyName, const XPropertyStateChangeListenerRef& Listener ) 1059 { 1060 } 1061 #endif 1062 1063 //======================================================================== 1064 //== OPropertyArrayHelper ================================================ 1065 //======================================================================== 1066 1067 //======================================================================== 1068 1069 // static OUString makeOUString( sal_Char *p ) 1070 // { 1071 // sal_Int32 nLen = strlen(p); 1072 // sal_Unicode *pw = new sal_Unicode[nLen]; 1073 1074 // for( int i = 0 ; i < nLen ; i ++ ) { 1075 1076 // // Only ascii strings allowed with this helper ! 1077 // OSL_ASSERT( p[i] < 127 ); 1078 // pw[i] = p[i]; 1079 // } 1080 // OUString ow( pw , nLen ); 1081 // delete pw; 1082 // return ow; 1083 // } 1084 1085 extern "C" { 1086 1087 static int compare_Property_Impl( const void *arg1, const void *arg2 ) 1088 SAL_THROW_EXTERN_C() 1089 { 1090 return ((Property *)arg1)->Name.compareTo( ((Property *)arg2)->Name ); 1091 } 1092 1093 } 1094 1095 void OPropertyArrayHelper::init( sal_Bool bSorted ) SAL_THROW( () ) 1096 { 1097 sal_Int32 i, nElements = aInfos.getLength(); 1098 const Property* pProperties = aInfos.getConstArray(); 1099 1100 for( i = 1; i < nElements; i++ ) 1101 { 1102 if( pProperties[i-1].Name >= pProperties[i].Name ) 1103 { 1104 #ifndef OS2 // YD disabled, too many troubles with debug builds! 1105 if (bSorted) { 1106 OSL_ENSURE( false, "Property array is not sorted" ); 1107 } 1108 #endif 1109 // not sorted 1110 qsort( aInfos.getArray(), nElements, sizeof( Property ), 1111 compare_Property_Impl ); 1112 break; 1113 } 1114 } 1115 // may be that the array is resorted 1116 pProperties = aInfos.getConstArray(); 1117 for( i = 0; i < nElements; i++ ) 1118 if( pProperties[i].Handle != i ) 1119 return; 1120 // The handle is the index 1121 bRightOrdered = sal_True; 1122 } 1123 1124 OPropertyArrayHelper::OPropertyArrayHelper( 1125 Property * pProps, 1126 sal_Int32 nEle, 1127 sal_Bool bSorted ) 1128 SAL_THROW( () ) 1129 : aInfos(pProps, nEle) 1130 , bRightOrdered( sal_False ) 1131 { 1132 init( bSorted ); 1133 } 1134 1135 OPropertyArrayHelper::OPropertyArrayHelper( 1136 const Sequence< Property > & aProps, 1137 sal_Bool bSorted ) 1138 SAL_THROW( () ) 1139 : aInfos(aProps) 1140 , bRightOrdered( sal_False ) 1141 { 1142 init( bSorted ); 1143 } 1144 1145 //======================================================================== 1146 sal_Int32 OPropertyArrayHelper::getCount() const 1147 { 1148 return aInfos.getLength(); 1149 } 1150 1151 //======================================================================== 1152 sal_Bool OPropertyArrayHelper::fillPropertyMembersByHandle 1153 ( 1154 OUString * pPropName, 1155 sal_Int16 * pAttributes, 1156 sal_Int32 nHandle 1157 ) 1158 { 1159 const Property* pProperties = aInfos.getConstArray(); 1160 sal_Int32 nElements = aInfos.getLength(); 1161 1162 if( bRightOrdered ) 1163 { 1164 if( nHandle < 0 || nHandle >= nElements ) 1165 return sal_False; 1166 if( pPropName ) 1167 *pPropName = pProperties[ nHandle ].Name; 1168 if( pAttributes ) 1169 *pAttributes = pProperties[ nHandle ].Attributes; 1170 return sal_True; 1171 } 1172 else 1173 { 1174 // normally the array is sorted 1175 for( sal_Int32 i = 0; i < nElements; i++ ) 1176 { 1177 if( pProperties[i].Handle == nHandle ) 1178 { 1179 if( pPropName ) 1180 *pPropName = pProperties[ i ].Name; 1181 if( pAttributes ) 1182 *pAttributes = pProperties[ i ].Attributes; 1183 return sal_True; 1184 } 1185 } 1186 } 1187 return sal_False; 1188 } 1189 1190 //======================================================================== 1191 Sequence< Property > OPropertyArrayHelper::getProperties(void) 1192 { 1193 /*if( aInfos.getLength() != nElements ) 1194 { 1195 ((OPropertyArrayHelper *)this)->aInfos.realloc( nElements ); 1196 Property * pProps = ((OPropertyArrayHelper *)this)->aInfos.getArray(); 1197 for( sal_Int32 i = 0; i < nElements; i++ ) 1198 { 1199 pProps[i].Name = pProperties[i].Name; 1200 pProps[i].Handle = pProperties[i].Handle; 1201 pProps[i].Type = pProperties[i].Type; 1202 pProps[i].Attributes = pProperties[i].Attributes; 1203 } 1204 }*/ 1205 return aInfos; 1206 } 1207 1208 //======================================================================== 1209 Property OPropertyArrayHelper::getPropertyByName(const OUString& aPropertyName) 1210 throw (UnknownPropertyException) 1211 { 1212 Property * pR; 1213 pR = (Property *)bsearch( &aPropertyName, aInfos.getConstArray(), aInfos.getLength(), 1214 sizeof( Property ), 1215 compare_OUString_Property_Impl ); 1216 if( !pR ) { 1217 throw UnknownPropertyException(); 1218 } 1219 1220 /*Property aProp; 1221 aProp.Name = pR->Name; 1222 aProp.Handle = pR->Handle; 1223 aProp.Type = pR->Type; 1224 aProp.Attributes = pR->Attributes; 1225 return aProp;*/ 1226 return *pR; 1227 } 1228 1229 //======================================================================== 1230 sal_Bool OPropertyArrayHelper::hasPropertyByName(const OUString& aPropertyName) 1231 { 1232 Property * pR; 1233 pR = (Property *)bsearch( &aPropertyName, aInfos.getConstArray(), aInfos.getLength(), 1234 sizeof( Property ), 1235 compare_OUString_Property_Impl ); 1236 return pR != NULL; 1237 } 1238 1239 //======================================================================== 1240 sal_Int32 OPropertyArrayHelper::getHandleByName( const OUString & rPropName ) 1241 { 1242 Property * pR; 1243 pR = (Property *)bsearch( &rPropName, aInfos.getConstArray(), aInfos.getLength(), 1244 sizeof( Property ), 1245 compare_OUString_Property_Impl ); 1246 return pR ? pR->Handle : -1; 1247 } 1248 1249 //======================================================================== 1250 sal_Int32 OPropertyArrayHelper::fillHandles( sal_Int32 * pHandles, const Sequence< OUString > & rPropNames ) 1251 { 1252 sal_Int32 nHitCount = 0; 1253 const OUString * pReqProps = rPropNames.getConstArray(); 1254 sal_Int32 nReqLen = rPropNames.getLength(); 1255 const Property * pCur = aInfos.getConstArray(); 1256 const Property * pEnd = pCur + aInfos.getLength(); 1257 1258 for( sal_Int32 i = 0; i < nReqLen; i++ ) 1259 { 1260 // Logarithmus ermitteln 1261 sal_Int32 n = (sal_Int32)(pEnd - pCur); 1262 sal_Int32 nLog = 0; 1263 while( n ) 1264 { 1265 nLog += 1; 1266 n = n >> 1; 1267 } 1268 1269 // Anzahl der noch zu suchenden Properties * dem Log2 der verbleibenden 1270 // zu dursuchenden Properties. 1271 if( (nReqLen - i) * nLog >= pEnd - pCur ) 1272 { 1273 // linear search is better 1274 while( pCur < pEnd && pReqProps[i] > pCur->Name ) 1275 { 1276 pCur++; 1277 } 1278 if( pCur < pEnd && pReqProps[i] == pCur->Name ) 1279 { 1280 pHandles[i] = pCur->Handle; 1281 nHitCount++; 1282 } 1283 else 1284 pHandles[i] = -1; 1285 } 1286 else 1287 { 1288 // binary search is better 1289 sal_Int32 nCompVal = 1; 1290 const Property * pOldEnd = pEnd--; 1291 const Property * pMid = pCur; 1292 1293 while( nCompVal != 0 && pCur <= pEnd ) 1294 { 1295 pMid = (pEnd - pCur) / 2 + pCur; 1296 1297 nCompVal = pReqProps[i].compareTo( pMid->Name ); 1298 1299 if( nCompVal > 0 ) 1300 pCur = pMid + 1; 1301 else 1302 pEnd = pMid - 1; 1303 } 1304 1305 if( nCompVal == 0 ) 1306 { 1307 pHandles[i] = pMid->Handle; 1308 nHitCount++; 1309 pCur = pMid +1; 1310 } 1311 else if( nCompVal > 0 ) 1312 { 1313 pHandles[i] = -1; 1314 pCur = pMid +1; 1315 } 1316 else 1317 { 1318 pHandles[i] = -1; 1319 pCur = pMid; 1320 } 1321 pEnd = pOldEnd; 1322 } 1323 } 1324 return nHitCount; 1325 } 1326 1327 } // end namespace cppu 1328 1329 1330 1331