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