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