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 3143 : IPropertyArrayHelper::~IPropertyArrayHelper()
42 : {
43 3143 : }
44 :
45 36047 : inline const ::com::sun::star::uno::Type & getPropertyTypeIdentifier( ) SAL_THROW(())
46 : {
47 36047 : return ::getCppuType( (Reference< XPropertyChangeListener > *)0 );
48 : }
49 34789 : inline const ::com::sun::star::uno::Type & getPropertiesTypeIdentifier() SAL_THROW(())
50 : {
51 34789 : return ::getCppuType( (Reference< XPropertiesChangeListener > *)0 );
52 : }
53 1321 : inline const ::com::sun::star::uno::Type & getVetoableTypeIdentifier() SAL_THROW(())
54 : {
55 1321 : return ::getCppuType( (Reference< XVetoableChangeListener > *)0 );
56 : }
57 :
58 : extern "C" {
59 :
60 6047297 : static int compare_OUString_Property_Impl( const void *arg1, const void *arg2 )
61 : SAL_THROW_EXTERN_C()
62 : {
63 6047297 : return ((OUString *)arg1)->compareTo( ((Property *)arg2)->Name );
64 : }
65 :
66 : }
67 :
68 : /**
69 : * The class which implements the PropertySetInfo interface.
70 : */
71 :
72 76272 : 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 38137 : OPropertySetHelperInfo_Impl::OPropertySetHelperInfo_Impl(
91 : IPropertyArrayHelper & rHelper_ )
92 : SAL_THROW(())
93 38137 : :aInfos( rHelper_.getProperties() )
94 : {
95 38137 : }
96 :
97 : /**
98 : * Return the sequence of properties, which are provided throug the constructor.
99 : */
100 5957 : Sequence< Property > OPropertySetHelperInfo_Impl::getProperties(void) throw(::com::sun::star::uno::RuntimeException)
101 :
102 : {
103 5957 : return aInfos;
104 : }
105 :
106 : /**
107 : * Return the sequence of properties, which are provided throug the constructor.
108 : */
109 110349 : Property OPropertySetHelperInfo_Impl::getPropertyByName( const OUString & PropertyName ) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::uno::RuntimeException)
110 : {
111 : Property * pR;
112 220698 : pR = (Property *)bsearch( &PropertyName, aInfos.getConstArray(), aInfos.getLength(),
113 : sizeof( Property ),
114 220698 : compare_OUString_Property_Impl );
115 110349 : if( !pR ) {
116 19 : throw UnknownPropertyException();
117 : }
118 :
119 110330 : return *pR;
120 : }
121 :
122 : /**
123 : * Return the sequence of properties, which are provided throug the constructor.
124 : */
125 242954 : sal_Bool OPropertySetHelperInfo_Impl::hasPropertyByName( const OUString & PropertyName ) throw(::com::sun::star::uno::RuntimeException)
126 : {
127 : Property * pR;
128 485908 : pR = (Property *)bsearch( &PropertyName, aInfos.getConstArray(), aInfos.getLength(),
129 : sizeof( Property ),
130 485908 : compare_OUString_Property_Impl );
131 242954 : return pR != NULL;
132 : }
133 :
134 : // ----------------------------------------------------
135 : // class PropertySetHelper_Impl
136 : // ----------------------------------------------------
137 67925 : class OPropertySetHelper::Impl {
138 :
139 : public:
140 68241 : Impl( bool i_bIgnoreRuntimeExceptionsWhileFiring,
141 : IEventNotificationHook *i_pFireEvents
142 : )
143 : :m_bIgnoreRuntimeExceptionsWhileFiring( i_bIgnoreRuntimeExceptionsWhileFiring )
144 : ,m_bFireEvents(true)
145 68241 : ,m_pFireEvents( i_pFireEvents )
146 : {
147 68241 : }
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 66936 : OPropertySetHelper::OPropertySetHelper(
163 : OBroadcastHelper & rBHelper_ ) SAL_THROW(())
164 : : rBHelper( rBHelper_ ),
165 : aBoundLC( rBHelper_.rMutex ),
166 : aVetoableLC( rBHelper_.rMutex ),
167 66936 : m_pReserved( new Impl(false, 0) )
168 : {
169 66936 : }
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 1305 : 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 1305 : new Impl( bIgnoreRuntimeExceptionsWhileFiring, i_pFireEvents) )
188 : {
189 1305 : }
190 :
191 1305 : OPropertySetHelper2::OPropertySetHelper2(
192 : OBroadcastHelper & irBHelper,
193 : IEventNotificationHook *i_pFireEvents,
194 : bool bIgnoreRuntimeExceptionsWhileFiring)
195 1305 : :OPropertySetHelper( irBHelper, i_pFireEvents, bIgnoreRuntimeExceptionsWhileFiring )
196 : {
197 1305 : }
198 :
199 : /**
200 : * You must call disposing before.
201 : */
202 67925 : OPropertySetHelper::~OPropertySetHelper() SAL_THROW(())
203 : {
204 67925 : }
205 1224 : OPropertySetHelper2::~OPropertySetHelper2() SAL_THROW(())
206 : {
207 1224 : }
208 :
209 : // XInterface
210 133840 : 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 133840 : static_cast< XFastPropertySet * >( this ) );
218 : }
219 :
220 86452 : Any OPropertySetHelper2::queryInterface( const ::com::sun::star::uno::Type & rType )
221 : throw (RuntimeException)
222 : {
223 86452 : Any cnd(cppu::queryInterface(rType, static_cast< XPropertySetOption * >(this)));
224 86452 : if ( cnd.hasValue() )
225 198 : return cnd;
226 : else
227 86254 : return OPropertySetHelper::queryInterface(rType);
228 : }
229 :
230 : /**
231 : * called from the derivee's XTypeProvider::getTypes implementation
232 : */
233 127 : ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > OPropertySetHelper::getTypes()
234 : throw (RuntimeException)
235 : {
236 127 : Sequence< ::com::sun::star::uno::Type > aTypes( 4 );
237 127 : aTypes[ 0 ] = XPropertySet::static_type();
238 127 : aTypes[ 1 ] = XPropertySetOption::static_type();
239 127 : aTypes[ 2 ] = XMultiPropertySet::static_type();
240 127 : aTypes[ 3 ] = XFastPropertySet::static_type();
241 127 : return aTypes;
242 : }
243 :
244 : // ComponentHelper
245 5738 : void OPropertySetHelper::disposing() SAL_THROW(())
246 : {
247 : // Create an event with this as sender
248 5738 : Reference < XPropertySet > rSource( (static_cast< XPropertySet * >(this)) , UNO_QUERY );
249 11476 : EventObject aEvt;
250 5738 : aEvt.Source = rSource;
251 :
252 : // inform all listeners to release this object
253 : // The listener containers are automatically cleared
254 5738 : aBoundLC.disposeAndClear( aEvt );
255 11476 : aVetoableLC.disposeAndClear( aEvt );
256 5738 : }
257 :
258 38137 : Reference < XPropertySetInfo > OPropertySetHelper::createPropertySetInfo(
259 : IPropertyArrayHelper & rProperties ) SAL_THROW(())
260 : {
261 38137 : return static_cast< XPropertySetInfo * >( new OPropertySetHelperInfo_Impl( rProperties ) );
262 : }
263 :
264 : // XPropertySet
265 117915 : 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 117915 : IPropertyArrayHelper & rPH = getInfoHelper();
271 : // map the name to the handle
272 117915 : sal_Int32 nHandle = rPH.getHandleByName( rPropertyName );
273 : // call the method of the XFastPropertySet interface
274 117915 : setFastPropertyValue( nHandle, rValue );
275 117794 : }
276 :
277 : // XPropertySet
278 770138 : 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 770138 : IPropertyArrayHelper & rPH = getInfoHelper();
284 : // map the name to the handle
285 770137 : sal_Int32 nHandle = rPH.getHandleByName( rPropertyName );
286 : // call the method of the XFastPropertySet interface
287 770138 : return getFastPropertyValue( nHandle );
288 : }
289 :
290 : // XPropertySet
291 9147 : 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 9147 : 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 9147 : 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 9147 : if( !rPropertyName.isEmpty() )
306 : {
307 : // get the map table
308 7985 : IPropertyArrayHelper & rPH = getInfoHelper();
309 : // map the name to the handle
310 7985 : sal_Int32 nHandle = rPH.getHandleByName( rPropertyName );
311 7985 : if( nHandle == -1 ) {
312 : // property not known throw exception
313 0 : throw UnknownPropertyException() ;
314 : }
315 :
316 : sal_Int16 nAttributes;
317 7985 : rPH.fillPropertyMembersByHandle( NULL, &nAttributes, nHandle );
318 7985 : if( !(nAttributes & ::com::sun::star::beans::PropertyAttribute::BOUND) )
319 : {
320 : OSL_FAIL( "add listener to an unbound property" );
321 : // silent ignore this
322 9147 : return;
323 : }
324 : // add the change listener to the helper container
325 :
326 7985 : aBoundLC.addInterface( (sal_Int32)nHandle, rxListener );
327 : }
328 : else
329 : // add the change listener to the helper container
330 : rBHelper.aLC.addInterface(
331 1162 : getPropertyTypeIdentifier( ),
332 : rxListener
333 2324 : );
334 9147 : }
335 : }
336 :
337 :
338 : // XPropertySet
339 5768 : 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 5768 : MutexGuard aGuard( rBHelper.rMutex );
347 : OSL_ENSURE( !rBHelper.bDisposed, "object is disposed" );
348 : // all listeners are automaticly released in a dispose call
349 5768 : if( !rBHelper.bInDispose && !rBHelper.bDisposed )
350 : {
351 5514 : if( !rPropertyName.isEmpty() )
352 : {
353 : // get the map table
354 4871 : IPropertyArrayHelper & rPH = getInfoHelper();
355 : // map the name to the handle
356 4871 : sal_Int32 nHandle = rPH.getHandleByName( rPropertyName );
357 4871 : if( nHandle == -1 )
358 : // property not known throw exception
359 0 : throw UnknownPropertyException();
360 4871 : aBoundLC.removeInterface( (sal_Int32)nHandle, rxListener );
361 : }
362 : else {
363 : // remove the change listener to the helper container
364 : rBHelper.aLC.removeInterface(
365 643 : getPropertyTypeIdentifier( ),
366 : rxListener
367 1286 : );
368 : }
369 5768 : }
370 5768 : }
371 :
372 : // XPropertySet
373 598 : 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 598 : 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 598 : 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 598 : if( !rPropertyName.isEmpty() )
388 : {
389 : // get the map table
390 31 : IPropertyArrayHelper & rPH = getInfoHelper();
391 : // map the name to the handle
392 31 : sal_Int32 nHandle = rPH.getHandleByName( rPropertyName );
393 31 : if( nHandle == -1 ) {
394 : // property not known throw exception
395 0 : throw UnknownPropertyException();
396 : }
397 :
398 : sal_Int16 nAttributes;
399 31 : rPH.fillPropertyMembersByHandle( NULL, &nAttributes, nHandle );
400 31 : if( !(nAttributes & PropertyAttribute::CONSTRAINED) )
401 : {
402 : OSL_FAIL( "addVetoableChangeListener, and property is not constrained" );
403 : // silent ignore this
404 598 : return;
405 : }
406 : // add the vetoable listener to the helper container
407 31 : aVetoableLC.addInterface( (sal_Int32)nHandle, rxListener );
408 : }
409 : else
410 : // add the vetoable listener to the helper container
411 : rBHelper.aLC.addInterface(
412 567 : getVetoableTypeIdentifier( ),
413 : rxListener
414 1134 : );
415 598 : }
416 : }
417 :
418 : // XPropertySet
419 517 : 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 517 : MutexGuard aGuard( rBHelper.rMutex );
427 : OSL_ENSURE( !rBHelper.bDisposed, "object is disposed" );
428 : // all listeners are automaticly released in a dispose call
429 517 : if( !rBHelper.bInDispose && !rBHelper.bDisposed )
430 : {
431 517 : if( !rPropertyName.isEmpty() )
432 : {
433 : // get the map table
434 1 : IPropertyArrayHelper & rPH = getInfoHelper();
435 : // map the name to the handle
436 1 : sal_Int32 nHandle = rPH.getHandleByName( rPropertyName );
437 1 : if( nHandle == -1 ) {
438 : // property not known throw exception
439 0 : throw UnknownPropertyException();
440 : }
441 : // remove the vetoable listener to the helper container
442 1 : aVetoableLC.removeInterface( (sal_Int32)nHandle, rxListener );
443 : }
444 : else
445 : // add the vetoable listener to the helper container
446 : rBHelper.aLC.removeInterface(
447 516 : getVetoableTypeIdentifier( ),
448 : rxListener
449 1032 : );
450 517 : }
451 517 : }
452 :
453 187 : 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 187 : sal_Int16 nAttributes(0);
459 187 : IPropertyArrayHelper& rInfo = getInfoHelper();
460 187 : 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 249 : Any aConverted, aOld;
469 187 : sal_Bool bChanged = convertFastPropertyValue( aConverted, aOld, i_handle, i_value );
470 187 : if ( !bChanged )
471 312 : 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 62 : 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 62 : m_pReserved->m_handles.push_back( i_handle );
500 62 : m_pReserved->m_newValues.push_back( aConverted ); // TODO: setFastPropertyValue notifies the unconverted value here ...?
501 124 : m_pReserved->m_oldValues.push_back( aOld );
502 : }
503 :
504 : // XFastPropertySet
505 116288 : 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 116288 : IPropertyArrayHelper & rInfo = getInfoHelper();
516 : sal_Int16 nAttributes;
517 116288 : if( !rInfo.fillPropertyMembersByHandle( NULL, &nAttributes, nHandle ) ) {
518 : // unknown property
519 69 : throw UnknownPropertyException();
520 : }
521 116219 : if( nAttributes & PropertyAttribute::READONLY )
522 32 : throw PropertyVetoException();
523 :
524 116187 : Any aConvertedVal;
525 232374 : Any aOldVal;
526 :
527 : // Will the property change?
528 : sal_Bool bChanged;
529 : {
530 116187 : MutexGuard aGuard( rBHelper.rMutex );
531 116191 : bChanged = convertFastPropertyValue( aConvertedVal, aOldVal, nHandle, rValue );
532 : // release guard to fire events
533 : }
534 116183 : if( bChanged )
535 : {
536 : // Is it a constrained property?
537 20650 : if( nAttributes & PropertyAttribute::CONSTRAINED )
538 : {
539 : // In aValue is the converted rValue
540 : // fire a constarined event
541 : // second parameter NULL means constrained
542 238 : fire( &nHandle, &rValue, &aOldVal, 1, sal_True );
543 : }
544 :
545 : {
546 20650 : MutexGuard aGuard( rBHelper.rMutex );
547 : try
548 : {
549 : // set the property to the new value
550 20650 : 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 20650 : }
566 :
567 : // release guard to fire events
568 : }
569 : // file a change event, if the value changed
570 20650 : impl_fireAll( &nHandle, &rValue, &aOldVal, 1 );
571 116187 : }
572 116183 : }
573 :
574 : // XFastPropertySet
575 824195 : 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 824195 : IPropertyArrayHelper & rInfo = getInfoHelper();
582 824195 : if( !rInfo.fillPropertyMembersByHandle( NULL, NULL, nHandle ) )
583 : // unknown property
584 1190 : throw UnknownPropertyException();
585 :
586 823005 : Any aRet;
587 1646010 : MutexGuard aGuard( rBHelper.rMutex );
588 823005 : getFastPropertyValue( aRet, nHandle );
589 1646010 : return aRet;
590 : }
591 :
592 : //--------------------------------------------------------------------------
593 30545 : void OPropertySetHelper::impl_fireAll( sal_Int32* i_handles, const Any* i_newValues, const Any* i_oldValues, sal_Int32 i_count )
594 : {
595 30545 : ClearableMutexGuard aGuard( rBHelper.rMutex );
596 30545 : if ( m_pReserved->m_handles.empty() )
597 : {
598 30487 : aGuard.clear();
599 30487 : fire( i_handles, i_newValues, i_oldValues, i_count, sal_False );
600 61032 : return;
601 : }
602 :
603 58 : 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 116 : ::std::vector< sal_Int32 > allHandles( additionalEvents + i_count );
609 58 : ::std::copy( m_pReserved->m_handles.begin(), m_pReserved->m_handles.end(), allHandles.begin() );
610 58 : ::std::copy( i_handles, i_handles + i_count, allHandles.begin() + additionalEvents );
611 :
612 116 : ::std::vector< Any > allNewValues( additionalEvents + i_count );
613 58 : ::std::copy( m_pReserved->m_newValues.begin(), m_pReserved->m_newValues.end(), allNewValues.begin() );
614 58 : ::std::copy( i_newValues, i_newValues + i_count, allNewValues.begin() + additionalEvents );
615 :
616 116 : ::std::vector< Any > allOldValues( additionalEvents + i_count );
617 58 : ::std::copy( m_pReserved->m_oldValues.begin(), m_pReserved->m_oldValues.end(), allOldValues.begin() );
618 58 : ::std::copy( i_oldValues, i_oldValues + i_count, allOldValues.begin() + additionalEvents );
619 :
620 58 : m_pReserved->m_handles.clear();
621 58 : m_pReserved->m_newValues.clear();
622 58 : m_pReserved->m_oldValues.clear();
623 :
624 58 : aGuard.clear();
625 116 : fire( &allHandles[0], &allNewValues[0], &allOldValues[0], additionalEvents + i_count, sal_False );
626 : }
627 :
628 : //--------------------------------------------------------------------------
629 49143 : 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 49143 : if (! m_pReserved->m_bFireEvents)
641 49218 : return;
642 :
643 49068 : if (m_pReserved->m_pFireEvents) {
644 24 : m_pReserved->m_pFireEvents->fireEvents(
645 : pnHandles, nHandles, bVetoable,
646 24 : m_pReserved->m_bIgnoreRuntimeExceptionsWhileFiring);
647 : }
648 :
649 : // Only fire, if one or more properties changed
650 49068 : if( nHandles )
651 : {
652 : // create the event sequence of all changed properties
653 43352 : Sequence< PropertyChangeEvent > aEvts( nHandles );
654 43352 : PropertyChangeEvent * pEvts = aEvts.getArray();
655 86704 : Reference < XInterface > xSource( (XPropertySet *)this, UNO_QUERY );
656 : sal_Int32 i;
657 43352 : sal_Int32 nChangesLen = 0;
658 : // Loop over all changed properties to fill the event struct
659 92685 : 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 49333 : IPropertyArrayHelper & rInfo = getInfoHelper();
664 : sal_Int16 nAttributes;
665 49333 : OUString aPropName;
666 49333 : rInfo.fillPropertyMembersByHandle( &aPropName, &nAttributes, pnHandles[i] );
667 :
668 49333 : if(
669 11200 : (bVetoable && (nAttributes & PropertyAttribute::CONSTRAINED)) ||
670 38133 : (!bVetoable && (nAttributes & PropertyAttribute::BOUND))
671 : )
672 : {
673 34480 : pEvts[nChangesLen].Source = xSource;
674 34480 : pEvts[nChangesLen].PropertyName = aPropName;
675 34480 : pEvts[nChangesLen].PropertyHandle = pnHandles[i];
676 34480 : pEvts[nChangesLen].OldValue = pOldValues[i];
677 34480 : pEvts[nChangesLen].NewValue = pNewValues[i];
678 34480 : nChangesLen++;
679 : }
680 49333 : }
681 :
682 : bool bIgnoreRuntimeExceptionsWhileFiring =
683 43352 : m_pReserved->m_bIgnoreRuntimeExceptionsWhileFiring;
684 :
685 : // fire the events for all changed properties
686 77832 : for( i = 0; i < nChangesLen; i++ )
687 : {
688 : // get the listener container for the property name
689 : OInterfaceContainerHelper * pLC;
690 34480 : if( bVetoable ) // fire change Events?
691 238 : pLC = aVetoableLC.getContainer( pEvts[i].PropertyHandle );
692 : else
693 34242 : pLC = aBoundLC.getContainer( pEvts[i].PropertyHandle );
694 34480 : if( pLC )
695 : {
696 : // Iterate over all listeners and send events
697 2812 : OInterfaceIteratorHelper aIt( *pLC);
698 7879 : while( aIt.hasMoreElements() )
699 : {
700 2255 : XInterface * pL = aIt.next();
701 : try
702 : {
703 : try
704 : {
705 2255 : if( bVetoable ) // fire change Events?
706 : {
707 : ((XVetoableChangeListener *)pL)->vetoableChange(
708 0 : pEvts[i] );
709 : }
710 : else
711 : {
712 : ((XPropertyChangeListener *)pL)->propertyChange(
713 2255 : 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 2812 : }
738 : }
739 : // broadcast to all listeners with "" property name
740 34480 : if( bVetoable ){
741 : // fire change Events?
742 : pLC = rBHelper.aLC.getContainer(
743 238 : getVetoableTypeIdentifier()
744 238 : );
745 : }
746 : else {
747 : pLC = rBHelper.aLC.getContainer(
748 34242 : getPropertyTypeIdentifier( )
749 34242 : );
750 : }
751 34480 : if( pLC )
752 : {
753 : // Iterate over all listeners and send events.
754 7211 : OInterfaceIteratorHelper aIt( *pLC);
755 26840 : while( aIt.hasMoreElements() )
756 : {
757 12418 : XInterface * pL = aIt.next();
758 : try
759 : {
760 : try
761 : {
762 12418 : if( bVetoable ) // fire change Events?
763 : {
764 : ((XVetoableChangeListener *)pL)->vetoableChange(
765 0 : pEvts[i] );
766 : }
767 : else
768 : {
769 : ((XPropertyChangeListener *)pL)->propertyChange(
770 12418 : 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 7211 : }
795 : }
796 : }
797 :
798 : // reduce array to changed properties
799 43352 : aEvts.realloc( nChangesLen );
800 :
801 43352 : if( !bVetoable )
802 : {
803 34789 : OInterfaceContainerHelper * pCont = 0;
804 : pCont = rBHelper.aLC.getContainer(
805 34789 : getPropertiesTypeIdentifier( )
806 34789 : );
807 34789 : if( pCont )
808 : {
809 : // Here is a Bug, unbound properties are also fired
810 10456 : OInterfaceIteratorHelper aIt( *pCont );
811 32391 : while( aIt.hasMoreElements() )
812 : {
813 : XPropertiesChangeListener * pL =
814 11479 : (XPropertiesChangeListener *)aIt.next();
815 : try
816 : {
817 : try
818 : {
819 : // fire the hole event sequence to the
820 : // XPropertiesChangeListener's
821 11479 : 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 10456 : }
845 : }
846 43352 : }
847 : }
848 : }
849 :
850 : // OPropertySetHelper
851 9919 : 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 9919 : Any * pConvertedValues = NULL;
862 9919 : Any * pOldValues = NULL;
863 :
864 : try
865 : {
866 : // get the map table
867 9919 : IPropertyArrayHelper & rPH = getInfoHelper();
868 :
869 9919 : pConvertedValues = new Any[ nHitCount ];
870 9919 : pOldValues = new Any[ nHitCount ];
871 9919 : sal_Int32 n = 0;
872 : sal_Int32 i;
873 :
874 : {
875 : // must lock the mutex outside the loop. So all values are consistent.
876 9919 : MutexGuard aGuard( rBHelper.rMutex );
877 67527 : for( i = 0; i < nSeqLen; i++ )
878 : {
879 57632 : if( pHandles[i] != -1 )
880 : {
881 : sal_Int16 nAttributes;
882 39517 : rPH.fillPropertyMembersByHandle( NULL, &nAttributes, pHandles[i] );
883 39517 : if( nAttributes & PropertyAttribute::READONLY ) {
884 0 : throw PropertyVetoException();
885 : }
886 : // Will the property change?
887 118527 : if( convertFastPropertyValue( pConvertedValues[ n ], pOldValues[n],
888 118551 : pHandles[i], pValues[i] ) )
889 : {
890 : // only increment if the property really change
891 10444 : pHandles[n] = pHandles[i];
892 10444 : n++;
893 : }
894 : }
895 9919 : }
896 : // release guard to fire events
897 : }
898 :
899 : // fire vetoable events
900 9895 : fire( pHandles, pConvertedValues, pOldValues, n, sal_True );
901 :
902 : {
903 : // must lock the mutex outside the loop.
904 9895 : MutexGuard aGuard( rBHelper.rMutex );
905 : // Loop over all changed properties
906 20335 : for( i = 0; i < n; i++ )
907 : {
908 : // Will the property change?
909 10440 : setFastPropertyValue_NoBroadcast( pHandles[i], pConvertedValues[i] );
910 9895 : }
911 : // release guard to fire events
912 : }
913 :
914 : // fire change events
915 9895 : impl_fireAll( pHandles, pConvertedValues, pOldValues, n );
916 : }
917 24 : catch( ... )
918 : {
919 24 : delete [] pOldValues;
920 24 : delete [] pConvertedValues;
921 24 : throw;
922 : }
923 9895 : delete [] pOldValues;
924 9895 : delete [] pConvertedValues;
925 9895 : }
926 :
927 : // XMultiPropertySet
928 : /**
929 : * The sequence may be conatain not known properties. The implementation
930 : * must ignore these properties.
931 : */
932 2136 : 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 2136 : sal_Int32 * pHandles = NULL;
938 : try
939 : {
940 2136 : sal_Int32 nSeqLen = rPropertyNames.getLength();
941 2136 : pHandles = new sal_Int32[ nSeqLen ];
942 : // get the map table
943 2136 : IPropertyArrayHelper & rPH = getInfoHelper();
944 : // fill the handle array
945 2136 : sal_Int32 nHitCount = rPH.fillHandles( pHandles, rPropertyNames );
946 2136 : if( nHitCount != 0 )
947 1736 : setFastPropertyValues( nSeqLen, pHandles, rValues.getConstArray(), nHitCount );
948 : }
949 3 : catch( ... )
950 : {
951 3 : delete [] pHandles;
952 3 : throw;
953 : }
954 2133 : delete [] pHandles;
955 2133 : }
956 :
957 : // XMultiPropertySet
958 3392 : Sequence<Any> OPropertySetHelper::getPropertyValues( const Sequence<OUString>& rPropertyNames )
959 : throw(::com::sun::star::uno::RuntimeException)
960 : {
961 3392 : sal_Int32 nSeqLen = rPropertyNames.getLength();
962 3392 : sal_Int32 * pHandles = new sal_Int32[ nSeqLen ];
963 3392 : Sequence< Any > aValues( nSeqLen );
964 :
965 : // get the map table
966 3392 : IPropertyArrayHelper & rPH = getInfoHelper();
967 : // fill the handle array
968 3392 : rPH.fillHandles( pHandles, rPropertyNames );
969 :
970 3392 : Any * pValues = aValues.getArray();
971 :
972 6784 : MutexGuard aGuard( rBHelper.rMutex );
973 : // fill the sequence with the values
974 67484 : for( sal_Int32 i = 0; i < nSeqLen; i++ )
975 64092 : getFastPropertyValue( pValues[i], pHandles[i] );
976 :
977 3392 : delete [] pHandles;
978 6784 : return aValues;
979 : }
980 :
981 : // XMultiPropertySet
982 1463 : void OPropertySetHelper::addPropertiesChangeListener(
983 : const Sequence<OUString> & ,
984 : const Reference < XPropertiesChangeListener > & rListener )
985 : throw(::com::sun::star::uno::RuntimeException)
986 : {
987 1463 : rBHelper.addListener( getCppuType(&rListener) , rListener );
988 1463 : }
989 :
990 : // XMultiPropertySet
991 1382 : void OPropertySetHelper::removePropertiesChangeListener(
992 : const Reference < XPropertiesChangeListener > & rListener )
993 : throw(::com::sun::star::uno::RuntimeException)
994 : {
995 1382 : rBHelper.removeListener( getCppuType(&rListener) , rListener );
996 1382 : }
997 :
998 : // XMultiPropertySet
999 411 : void OPropertySetHelper::firePropertiesChangeEvent(
1000 : const Sequence<OUString>& rPropertyNames,
1001 : const Reference < XPropertiesChangeListener >& rListener )
1002 : throw(::com::sun::star::uno::RuntimeException)
1003 : {
1004 411 : sal_Int32 nLen = rPropertyNames.getLength();
1005 411 : sal_Int32 * pHandles = new sal_Int32[nLen];
1006 411 : IPropertyArrayHelper & rPH = getInfoHelper();
1007 411 : rPH.fillHandles( pHandles, rPropertyNames );
1008 411 : const OUString* pNames = rPropertyNames.getConstArray();
1009 :
1010 : // get the count of matching properties
1011 411 : sal_Int32 nFireLen = 0;
1012 : sal_Int32 i;
1013 28290 : for( i = 0; i < nLen; i++ )
1014 27879 : if( pHandles[i] != -1 )
1015 27879 : nFireLen++;
1016 :
1017 411 : Sequence<PropertyChangeEvent> aChanges( nFireLen );
1018 411 : PropertyChangeEvent* pChanges = aChanges.getArray();
1019 :
1020 : {
1021 : // must lock the mutex outside the loop. So all values are consistent.
1022 411 : MutexGuard aGuard( rBHelper.rMutex );
1023 822 : Reference < XInterface > xSource( (XPropertySet *)this, UNO_QUERY );
1024 411 : sal_Int32 nFirePos = 0;
1025 28290 : for( i = 0; i < nLen; i++ )
1026 : {
1027 27879 : if( pHandles[i] != -1 )
1028 : {
1029 27879 : pChanges[nFirePos].Source = xSource;
1030 27879 : pChanges[nFirePos].PropertyName = pNames[i];
1031 27879 : pChanges[nFirePos].PropertyHandle = pHandles[i];
1032 27879 : getFastPropertyValue( pChanges[nFirePos].OldValue, pHandles[i] );
1033 27879 : pChanges[nFirePos].NewValue = pChanges[nFirePos].OldValue;
1034 27879 : nFirePos++;
1035 : }
1036 411 : }
1037 : // release guard to fire events
1038 : }
1039 411 : if( nFireLen )
1040 411 : rListener->propertiesChange( aChanges );
1041 :
1042 411 : delete [] pHandles;
1043 411 : }
1044 :
1045 198 : void OPropertySetHelper2::enableChangeListenerNotification( sal_Bool bEnable )
1046 : throw(::com::sun::star::uno::RuntimeException)
1047 : {
1048 198 : m_pReserved->m_bFireEvents = bEnable;
1049 198 : }
1050 :
1051 : //========================================================================
1052 : //== OPropertyArrayHelper ================================================
1053 : //========================================================================
1054 :
1055 : extern "C" {
1056 :
1057 76929 : static int compare_Property_Impl( const void *arg1, const void *arg2 )
1058 : SAL_THROW_EXTERN_C()
1059 : {
1060 76929 : return ((Property *)arg1)->Name.compareTo( ((Property *)arg2)->Name );
1061 : }
1062 :
1063 : }
1064 :
1065 2461 : void OPropertyArrayHelper::init( sal_Bool bSorted ) SAL_THROW(())
1066 : {
1067 2461 : sal_Int32 i, nElements = aInfos.getLength();
1068 2461 : const Property* pProperties = aInfos.getConstArray();
1069 :
1070 49339 : for( i = 1; i < nElements; i++ )
1071 : {
1072 47425 : 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 547 : qsort( aInfos.getArray(), nElements, sizeof( Property ),
1079 1094 : compare_Property_Impl );
1080 547 : break;
1081 : }
1082 : }
1083 : // may be that the array is resorted
1084 2461 : pProperties = aInfos.getConstArray();
1085 2585 : for( i = 0; i < nElements; i++ )
1086 2453 : if( pProperties[i].Handle != i )
1087 4790 : return;
1088 : // The handle is the index
1089 132 : 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 2461 : OPropertyArrayHelper::OPropertyArrayHelper(
1104 : const Sequence< Property > & aProps,
1105 : sal_Bool bSorted )
1106 : SAL_THROW(())
1107 : : aInfos(aProps)
1108 2461 : , bRightOrdered( sal_False )
1109 : {
1110 2461 : init( bSorted );
1111 2461 : }
1112 :
1113 : //========================================================================
1114 0 : sal_Int32 OPropertyArrayHelper::getCount() const
1115 : {
1116 0 : return aInfos.getLength();
1117 : }
1118 :
1119 : //========================================================================
1120 935127 : sal_Bool OPropertyArrayHelper::fillPropertyMembersByHandle
1121 : (
1122 : OUString * pPropName,
1123 : sal_Int16 * pAttributes,
1124 : sal_Int32 nHandle
1125 : )
1126 : {
1127 935127 : const Property* pProperties = aInfos.getConstArray();
1128 935127 : sal_Int32 nElements = aInfos.getLength();
1129 :
1130 935127 : if( bRightOrdered )
1131 : {
1132 169 : if( nHandle < 0 || nHandle >= nElements )
1133 0 : return sal_False;
1134 169 : if( pPropName )
1135 1 : *pPropName = pProperties[ nHandle ].Name;
1136 169 : if( pAttributes )
1137 2 : *pAttributes = pProperties[ nHandle ].Attributes;
1138 169 : return sal_True;
1139 : }
1140 : else
1141 : {
1142 : // normally the array is sorted
1143 27865154 : for( sal_Int32 i = 0; i < nElements; i++ )
1144 : {
1145 27864068 : if( pProperties[i].Handle == nHandle )
1146 : {
1147 933872 : if( pPropName )
1148 45994 : *pPropName = pProperties[ i ].Name;
1149 933872 : if( pAttributes )
1150 178796 : *pAttributes = pProperties[ i ].Attributes;
1151 933872 : return sal_True;
1152 : }
1153 : }
1154 : }
1155 1086 : return sal_False;
1156 : }
1157 :
1158 : //========================================================================
1159 15481 : Sequence< Property > OPropertyArrayHelper::getProperties(void)
1160 : {
1161 15481 : 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 914878 : sal_Int32 OPropertyArrayHelper::getHandleByName( const OUString & rPropName )
1190 : {
1191 : Property * pR;
1192 1829756 : pR = (Property *)bsearch( &rPropName, aInfos.getConstArray(), aInfos.getLength(),
1193 : sizeof( Property ),
1194 1829756 : compare_OUString_Property_Impl );
1195 914878 : return pR ? pR->Handle : -1;
1196 : }
1197 :
1198 : //========================================================================
1199 2239 : sal_Int32 OPropertyArrayHelper::fillHandles( sal_Int32 * pHandles, const Sequence< OUString > & rPropNames )
1200 : {
1201 2239 : sal_Int32 nHitCount = 0;
1202 2239 : const OUString * pReqProps = rPropNames.getConstArray();
1203 2239 : sal_Int32 nReqLen = rPropNames.getLength();
1204 2239 : const Property * pCur = aInfos.getConstArray();
1205 2239 : const Property * pEnd = pCur + aInfos.getLength();
1206 :
1207 15673 : for( sal_Int32 i = 0; i < nReqLen; i++ )
1208 : {
1209 : // Calculate logarithm
1210 13434 : sal_Int32 n = (sal_Int32)(pEnd - pCur);
1211 13434 : sal_Int32 nLog = 0;
1212 99203 : while( n )
1213 : {
1214 72335 : nLog += 1;
1215 72335 : n = n >> 1;
1216 : }
1217 :
1218 : // Number of properties to search for * Log2 of the number of remaining
1219 : // properties to search in.
1220 13434 : if( (nReqLen - i) * nLog >= pEnd - pCur )
1221 : {
1222 : // linear search is better
1223 24011 : while( pCur < pEnd && pReqProps[i] > pCur->Name )
1224 : {
1225 8105 : pCur++;
1226 : }
1227 7953 : if( pCur < pEnd && pReqProps[i] == pCur->Name )
1228 : {
1229 7945 : pHandles[i] = pCur->Handle;
1230 7945 : nHitCount++;
1231 : }
1232 : else
1233 8 : pHandles[i] = -1;
1234 : }
1235 : else
1236 : {
1237 : // binary search is better
1238 5481 : sal_Int32 nCompVal = 1;
1239 5481 : const Property * pOldEnd = pEnd--;
1240 5481 : const Property * pMid = pCur;
1241 :
1242 36748 : while( nCompVal != 0 && pCur <= pEnd )
1243 : {
1244 25786 : pMid = (pEnd - pCur) / 2 + pCur;
1245 :
1246 25786 : nCompVal = pReqProps[i].compareTo( pMid->Name );
1247 :
1248 25786 : if( nCompVal > 0 )
1249 6405 : pCur = pMid + 1;
1250 : else
1251 19381 : pEnd = pMid - 1;
1252 : }
1253 :
1254 5481 : if( nCompVal == 0 )
1255 : {
1256 5481 : pHandles[i] = pMid->Handle;
1257 5481 : nHitCount++;
1258 5481 : 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 5481 : pEnd = pOldEnd;
1271 : }
1272 : }
1273 2239 : return nHitCount;
1274 : }
1275 :
1276 : } // end namespace cppu
1277 :
1278 :
1279 :
1280 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|