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