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