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