xref: /trunk/main/cppuhelper/source/propshlp.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
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