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