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