1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_comphelper.hxx"
26 #include <comphelper/propertycontainerhelper.hxx>
27 #include <comphelper/property.hxx>
28 #include <osl/diagnose.h>
29 #include <uno/data.h>
30 #include <com/sun/star/uno/genfunc.h>
31 #include <com/sun/star/beans/PropertyAttribute.hpp>
32 #include <com/sun/star/beans/UnknownPropertyException.hpp>
33 #include <rtl/ustrbuf.hxx>
34 
35 #include <algorithm>
36 
37 //.........................................................................
38 namespace comphelper
39 {
40 //.........................................................................
41 
42 using namespace ::com::sun::star::uno;
43 using namespace ::com::sun::star::lang;
44 using namespace ::com::sun::star::beans;
45 
46 //--------------------------------------------------------------------------
47 namespace
48 {
49 	// comparing two property descriptions
50 	struct PropertyDescriptionCompareByHandle : public ::std::binary_function< PropertyDescription, PropertyDescription, bool >
51 	{
operator ()comphelper::__anonfd13eaa90111::PropertyDescriptionCompareByHandle52 		bool operator() (const PropertyDescription& x, const PropertyDescription& y) const
53 		{
54 			return x.aProperty.Handle < y.aProperty.Handle;
55 		}
56 	};
57 	// comparing two property descriptions
58 	struct PropertyDescriptionHandleCompare : public ::std::binary_function< PropertyDescription, sal_Int32, bool >
59 	{
operator ()comphelper::__anonfd13eaa90111::PropertyDescriptionHandleCompare60 		bool operator() (const PropertyDescription& x, const sal_Int32& y) const
61 		{
62 			return x.aProperty.Handle < y;
63 		}
operator ()comphelper::__anonfd13eaa90111::PropertyDescriptionHandleCompare64 		bool operator() (const sal_Int32& x, const PropertyDescription& y) const
65 		{
66 			return x < y.aProperty.Handle;
67 		}
68 	};
69 	// comparing two property descriptions (by name)
70     struct PropertyDescriptionNameMatch : public ::std::unary_function< PropertyDescription, bool >
71 	{
72         ::rtl::OUString m_rCompare;
PropertyDescriptionNameMatchcomphelper::__anonfd13eaa90111::PropertyDescriptionNameMatch73         PropertyDescriptionNameMatch( const ::rtl::OUString& _rCompare ) : m_rCompare( _rCompare ) { }
74 
operator ()comphelper::__anonfd13eaa90111::PropertyDescriptionNameMatch75         bool operator() (const PropertyDescription& x ) const
76 		{
77 			return x.aProperty.Name.equals(m_rCompare);
78 		}
79 	};
80 }
81 
82 //==========================================================================
83 //= OPropertyContainerHelper
84 //==========================================================================
85 //--------------------------------------------------------------------------
OPropertyContainerHelper()86 OPropertyContainerHelper::OPropertyContainerHelper()
87     :m_bUnused(sal_False)
88 {
89 }
90 
91 // -------------------------------------------------------------------------
~OPropertyContainerHelper()92 OPropertyContainerHelper::~OPropertyContainerHelper()
93 {
94 }
95 
96 //--------------------------------------------------------------------------
registerProperty(const::rtl::OUString & _rName,sal_Int32 _nHandle,sal_Int32 _nAttributes,void * _pPointerToMember,const Type & _rMemberType)97 void OPropertyContainerHelper::registerProperty(const ::rtl::OUString& _rName, sal_Int32 _nHandle,
98 		sal_Int32 _nAttributes, void* _pPointerToMember, const Type& _rMemberType)
99 {
100 	OSL_ENSURE((_nAttributes & PropertyAttribute::MAYBEVOID) == 0,
101 		"OPropertyContainerHelper::registerProperty: don't use this for properties which may be void ! There is a method called \"registerMayBeVoidProperty\" for this !");
102 	OSL_ENSURE(!_rMemberType.equals(::getCppuType(static_cast< Any* >(NULL))),
103 		"OPropertyContainerHelper::registerProperty: don't give my the type of an uno::Any ! Really can't handle this !");
104 	OSL_ENSURE(_pPointerToMember,
105 		"OPropertyContainerHelper::registerProperty: you gave me nonsense : the pointer must be non-NULL");
106 
107 	PropertyDescription aNewProp;
108 	aNewProp.aProperty = Property( _rName, _nHandle, _rMemberType, (sal_Int16)_nAttributes );
109 	aNewProp.eLocated = PropertyDescription::ltDerivedClassRealType;
110 	aNewProp.aLocation.pDerivedClassMember = _pPointerToMember;
111 
112 	implPushBackProperty(aNewProp);
113 }
114 
115 //--------------------------------------------------------------------------
revokeProperty(sal_Int32 _nHandle)116 void OPropertyContainerHelper::revokeProperty( sal_Int32 _nHandle )
117 {
118     PropertiesIterator aPos = searchHandle( _nHandle );
119     if ( aPos == m_aProperties.end() )
120         throw UnknownPropertyException();
121     m_aProperties.erase( aPos );
122 }
123 
124 //--------------------------------------------------------------------------
registerMayBeVoidProperty(const::rtl::OUString & _rName,sal_Int32 _nHandle,sal_Int32 _nAttributes,Any * _pPointerToMember,const Type & _rExpectedType)125 void OPropertyContainerHelper::registerMayBeVoidProperty(const ::rtl::OUString& _rName, sal_Int32 _nHandle, sal_Int32 _nAttributes,
126 		Any* _pPointerToMember, const Type& _rExpectedType)
127 {
128 	OSL_ENSURE((_nAttributes & PropertyAttribute::MAYBEVOID) != 0,
129 		"OPropertyContainerHelper::registerMayBeVoidProperty: why calling this when the attributes say nothing about may-be-void ?");
130 	OSL_ENSURE(!_rExpectedType.equals(::getCppuType(static_cast< Any* >(NULL))),
131 		"OPropertyContainerHelper::registerMayBeVoidProperty: don't give my the type of an uno::Any ! Really can't handle this !");
132 	OSL_ENSURE(_pPointerToMember,
133 		"OPropertyContainerHelper::registerMayBeVoidProperty: you gave me nonsense : the pointer must be non-NULL");
134 
135 	_nAttributes |= PropertyAttribute::MAYBEVOID;
136 
137 	PropertyDescription aNewProp;
138 	aNewProp.aProperty = Property( _rName, _nHandle, _rExpectedType, (sal_Int16)_nAttributes );
139 	aNewProp.eLocated = PropertyDescription::ltDerivedClassAnyType;
140 	aNewProp.aLocation.pDerivedClassMember = _pPointerToMember;
141 
142 	implPushBackProperty(aNewProp);
143 }
144 
145 
146 //--------------------------------------------------------------------------
registerPropertyNoMember(const::rtl::OUString & _rName,sal_Int32 _nHandle,sal_Int32 _nAttributes,const Type & _rType,const void * _pInitialValue)147 void OPropertyContainerHelper::registerPropertyNoMember(const ::rtl::OUString& _rName, sal_Int32 _nHandle, sal_Int32 _nAttributes,
148 		const Type& _rType, const void* _pInitialValue)
149 {
150 	OSL_ENSURE(!_rType.equals(::getCppuType(static_cast< Any* >(NULL))),
151 		"OPropertyContainerHelper::registerPropertyNoMember : don't give my the type of an uno::Any ! Really can't handle this !");
152 	OSL_ENSURE(_pInitialValue || ((_nAttributes & PropertyAttribute::MAYBEVOID) != 0),
153 		"OPropertyContainerHelper::registerPropertyNoMember : you should not ommit the initial value if the property can't be void ! This will definitivly crash later !");
154 
155 	PropertyDescription aNewProp;
156 	aNewProp.aProperty = Property( _rName, _nHandle, _rType, (sal_Int16)_nAttributes );
157 	aNewProp.eLocated = PropertyDescription::ltHoldMyself;
158 	aNewProp.aLocation.nOwnClassVectorIndex = m_aHoldProperties.size();
159 	if (_pInitialValue)
160 		m_aHoldProperties.push_back(Any(_pInitialValue, _rType));
161 	else
162 		m_aHoldProperties.push_back(Any());
163 
164 	implPushBackProperty(aNewProp);
165 }
166 
167 //--------------------------------------------------------------------------
isRegisteredProperty(sal_Int32 _nHandle) const168 sal_Bool OPropertyContainerHelper::isRegisteredProperty( sal_Int32 _nHandle ) const
169 {
170     return const_cast< OPropertyContainerHelper* >( this )->searchHandle( _nHandle ) != m_aProperties.end();
171 }
172 
173 //--------------------------------------------------------------------------
isRegisteredProperty(const::rtl::OUString & _rName) const174 sal_Bool OPropertyContainerHelper::isRegisteredProperty( const ::rtl::OUString& _rName ) const
175 {
176     // TODO: the current structure is from a time where properties were
177     // static, not dynamic. Since we allow that properties are also dynamic,
178     // i.e. registered and revoked even though the XPropertySet has already been
179     // accessed, a vector is not really the best data structure anymore ...
180 
181     ConstPropertiesIterator pos = ::std::find_if(
182         m_aProperties.begin(),
183         m_aProperties.end(),
184         PropertyDescriptionNameMatch( _rName )
185     );
186     return pos != m_aProperties.end();
187 }
188 
189 //--------------------------------------------------------------------------
190 namespace
191 {
192     struct ComparePropertyWithHandle
193     {
operator ()comphelper::__anonfd13eaa90211::ComparePropertyWithHandle194         bool operator()( const PropertyDescription& _rLHS, sal_Int32 _nRHS ) const
195         {
196             return _rLHS.aProperty.Handle < _nRHS;
197         }
operator ()comphelper::__anonfd13eaa90211::ComparePropertyWithHandle198         bool operator()( sal_Int32 _nLHS, const PropertyDescription& _rRHS ) const
199         {
200             return _nLHS < _rRHS.aProperty.Handle;
201         }
202     };
203 }
204 
205 //--------------------------------------------------------------------------
implPushBackProperty(const PropertyDescription & _rProp)206 void OPropertyContainerHelper::implPushBackProperty(const PropertyDescription& _rProp)
207 {
208 #ifdef DBG_UTIL
209 	for	(	PropertiesIterator checkConflicts = m_aProperties.begin();
210 			checkConflicts != m_aProperties.end();
211 			++checkConflicts
212 		)
213 	{
214 		OSL_ENSURE(checkConflicts->aProperty.Name != _rProp.aProperty.Name, "OPropertyContainerHelper::implPushBackProperty: name already exists!");
215 		OSL_ENSURE(checkConflicts->aProperty.Handle != _rProp.aProperty.Handle, "OPropertyContainerHelper::implPushBackProperty: handle already exists!");
216 	}
217 #endif
218 
219     PropertiesIterator pos = ::std::lower_bound(
220         m_aProperties.begin(), m_aProperties.end(),
221         _rProp.aProperty.Handle, ComparePropertyWithHandle() );
222 
223     m_aProperties.insert( pos, _rProp );
224 }
225 
226 //--------------------------------------------------------------------------
227 namespace
228 {
lcl_throwIllegalPropertyValueTypeException(const PropertyDescription & _rProperty,const Any & _rValue)229     void lcl_throwIllegalPropertyValueTypeException( const PropertyDescription& _rProperty, const Any& _rValue )
230     {
231         ::rtl::OUStringBuffer aErrorMessage;
232         aErrorMessage.appendAscii( "The given value cannot be converted to the required property type." );
233         aErrorMessage.appendAscii( "\n(property name \"" );
234         aErrorMessage.append( _rProperty.aProperty.Name );
235         aErrorMessage.appendAscii( "\", found value type \"" );
236         aErrorMessage.append( _rValue.getValueType().getTypeName() );
237         aErrorMessage.appendAscii( "\", required property type \"" );
238         aErrorMessage.append( _rProperty.aProperty.Type.getTypeName() );
239         aErrorMessage.appendAscii( "\")" );
240 		throw IllegalArgumentException( aErrorMessage.makeStringAndClear(), NULL, 4 );
241     }
242 }
243 
244 //--------------------------------------------------------------------------
convertFastPropertyValue(Any & _rConvertedValue,Any & _rOldValue,sal_Int32 _nHandle,const Any & _rValue)245 sal_Bool OPropertyContainerHelper::convertFastPropertyValue(
246 	Any& _rConvertedValue, Any& _rOldValue, sal_Int32 _nHandle, const Any& _rValue ) SAL_THROW( (IllegalArgumentException) )
247 {
248 	sal_Bool bModified = sal_False;
249 
250 	// get the property somebody is asking for
251 	PropertiesIterator aPos = searchHandle(_nHandle);
252 	if (aPos == m_aProperties.end())
253 	{
254 		OSL_ENSURE( false, "OPropertyContainerHelper::convertFastPropertyValue: unknown handle!" );
255 		// should not happen if the derived class has built a correct property set info helper to be used by
256 		// our base class OPropertySetHelper
257 		return bModified;
258 	}
259 
260 	switch (aPos->eLocated)
261 	{
262 		// similar handling for the two cases where the value is stored in an any
263 		case PropertyDescription::ltHoldMyself:
264 		case PropertyDescription::ltDerivedClassAnyType:
265 		{
266 			sal_Bool bMayBeVoid = ((aPos->aProperty.Attributes & PropertyAttribute::MAYBEVOID) != 0);
267 
268 
269 			// non modifiable version of the value-to-be-set
270 			Any aNewRequestedValue( _rValue );
271 
272 			// normalization
273 			// (#102329# - 2002-08-14 - fs@openoffice.org)
274 			// (#i29490# - 2004-06-16 - fs@openoffice.org)
275 			if ( !aNewRequestedValue.getValueType().equals( aPos->aProperty.Type ) )
276 			{	// the actually given value is not of the same type as the one required
277 				Any aProperlyTyped( NULL, aPos->aProperty.Type.getTypeLibType() );
278 
279 				if (	uno_type_assignData(
280 							const_cast< void* >( aProperlyTyped.getValue() ), aProperlyTyped.getValueType().getTypeLibType(),
281 							const_cast< void* >( aNewRequestedValue.getValue() ), aNewRequestedValue.getValueType().getTypeLibType(),
282 							reinterpret_cast< uno_QueryInterfaceFunc >( cpp_queryInterface ),
283                             reinterpret_cast< uno_AcquireFunc >( cpp_acquire ),
284                             reinterpret_cast< uno_ReleaseFunc >( cpp_release )
285 						)
286 					)
287 				{
288 					// we were able to query the given XInterface-derivee for the interface
289 					// which is required for this property
290 					aNewRequestedValue = aProperlyTyped;
291 				}
292 			}
293 
294 			// argument check
295 			if	(	!	(	(bMayBeVoid && !aNewRequestedValue.hasValue())			            // void is allowed if the attribute says so
296 						||	(aNewRequestedValue.getValueType().equals(aPos->aProperty.Type))	// else the types have to be equal
297 						)
298 				)
299 			{
300                 lcl_throwIllegalPropertyValueTypeException( *aPos, _rValue );
301 			}
302 
303 			Any* pPropContainer = NULL;
304 				// the pointer to the any which holds the property value, no matter if located in the derived clas
305 				// or in out vector
306 
307 			if (PropertyDescription::ltHoldMyself == aPos->eLocated)
308 			{
309 				OSL_ENSURE(aPos->aLocation.nOwnClassVectorIndex < (sal_Int32)m_aHoldProperties.size(),
310 					"OPropertyContainerHelper::convertFastPropertyValue: invalid position !");
311 				PropertyContainerIterator aIter = m_aHoldProperties.begin() + aPos->aLocation.nOwnClassVectorIndex;
312 				pPropContainer = &(*aIter);
313 			}
314 			else
315 				pPropContainer = reinterpret_cast<Any*>(aPos->aLocation.pDerivedClassMember);
316 
317 			// check if the new value differs from the current one
318 			if (!pPropContainer->hasValue() || !aNewRequestedValue.hasValue())
319 				bModified = pPropContainer->hasValue() != aNewRequestedValue.hasValue();
320 			else
321 				bModified = !uno_type_equalData(
322                                 const_cast< void* >( pPropContainer->getValue() ), aPos->aProperty.Type.getTypeLibType(),
323                                 const_cast< void* >( aNewRequestedValue.getValue() ), aPos->aProperty.Type.getTypeLibType(),
324                                 reinterpret_cast< uno_QueryInterfaceFunc >( cpp_queryInterface ),
325                                 reinterpret_cast< uno_ReleaseFunc >( cpp_release )
326 							);
327 
328 			if (bModified)
329 			{
330 				_rOldValue = *pPropContainer;
331 				_rConvertedValue = aNewRequestedValue;
332 			}
333 		}
334 		break;
335 		case PropertyDescription::ltDerivedClassRealType:
336 			// let the UNO runtime library do any possible conversion
337 			// this may include a change of the type - for instance, if a LONG is required,
338 			// but a short is given, then this is valid, as it can be converted without any potential
339 			// data loss
340 
341 			Any aProperlyTyped;
342 			const Any* pNewValue = &_rValue;
343 
344 			if (!_rValue.getValueType().equals(aPos->aProperty.Type))
345 			{
346 				sal_Bool bConverted = sal_False;
347 
348 				// a temporary any of the correct (required) type
349 				aProperlyTyped = Any( NULL, aPos->aProperty.Type.getTypeLibType() );
350 					// (need this as we do not want to overwrite the derived class member here)
351 
352 				if (	uno_type_assignData(
353 							const_cast<void*>(aProperlyTyped.getValue()), aProperlyTyped.getValueType().getTypeLibType(),
354 							const_cast<void*>(_rValue.getValue()), _rValue.getValueType().getTypeLibType(),
355 							reinterpret_cast< uno_QueryInterfaceFunc >( cpp_queryInterface ),
356                             reinterpret_cast< uno_AcquireFunc >( cpp_acquire ),
357                             reinterpret_cast< uno_ReleaseFunc >( cpp_release )
358 						)
359 					)
360 				{
361 					// could query for the requested interface
362 					bConverted = sal_True;
363 					pNewValue = &aProperlyTyped;
364 				}
365 
366 				if ( !bConverted )
367                     lcl_throwIllegalPropertyValueTypeException( *aPos, _rValue );
368 			}
369 
370 			// from here on, we should have the proper type
371 			OSL_ENSURE( pNewValue->getValueType() == aPos->aProperty.Type,
372 				"OPropertyContainerHelper::convertFastPropertyValue: conversion failed!" );
373 			bModified = !uno_type_equalData(
374                             aPos->aLocation.pDerivedClassMember, aPos->aProperty.Type.getTypeLibType(),
375                             const_cast<void*>(pNewValue->getValue()), aPos->aProperty.Type.getTypeLibType(),
376                             reinterpret_cast< uno_QueryInterfaceFunc >( cpp_queryInterface ),
377                             reinterpret_cast< uno_ReleaseFunc >( cpp_release )
378 						);
379 
380 			if (bModified)
381 			{
382 				_rOldValue.setValue(aPos->aLocation.pDerivedClassMember, aPos->aProperty.Type);
383 				_rConvertedValue = *pNewValue;
384 			}
385 			break;
386 	}
387 
388 	return bModified;
389 }
390 
391 //--------------------------------------------------------------------------
setFastPropertyValue(sal_Int32 _nHandle,const Any & _rValue)392 void OPropertyContainerHelper::setFastPropertyValue(sal_Int32 _nHandle, const Any& _rValue) SAL_THROW( (Exception) )
393 {
394 	// get the property somebody is asking for
395 	PropertiesIterator aPos = searchHandle(_nHandle);
396 	if (aPos == m_aProperties.end())
397 	{
398 		OSL_ENSURE( false, "OPropertyContainerHelper::setFastPropertyValue: unknown handle!" );
399 		// should not happen if the derived class has built a correct property set info helper to be used by
400 		// our base class OPropertySetHelper
401 		return;
402 	}
403 
404 	switch (aPos->eLocated)
405 	{
406 		case PropertyDescription::ltHoldMyself:
407 			m_aHoldProperties[aPos->aLocation.nOwnClassVectorIndex] = _rValue;
408 			break;
409 
410 		case PropertyDescription::ltDerivedClassAnyType:
411 			*reinterpret_cast< Any* >(aPos->aLocation.pDerivedClassMember) = _rValue;
412 			break;
413 
414 		case PropertyDescription::ltDerivedClassRealType:
415 #if OSL_DEBUG_LEVEL > 0
416 			sal_Bool bSuccess =
417 #endif
418 			// copy the data from the to-be-set value
419 			uno_type_assignData(
420 				aPos->aLocation.pDerivedClassMember,		aPos->aProperty.Type.getTypeLibType(),
421 				const_cast< void* >( _rValue.getValue() ),	_rValue.getValueType().getTypeLibType(),
422 				reinterpret_cast< uno_QueryInterfaceFunc >( cpp_queryInterface ),
423 				reinterpret_cast< uno_AcquireFunc >( cpp_acquire ),
424                 reinterpret_cast< uno_ReleaseFunc >( cpp_release ) );
425 
426 			OSL_ENSURE( bSuccess,
427 				"OPropertyContainerHelper::setFastPropertyValue: ooops .... the value could not be assigned!");
428 
429 			break;
430 	}
431 }
432 
433 //--------------------------------------------------------------------------
getFastPropertyValue(Any & _rValue,sal_Int32 _nHandle) const434 void OPropertyContainerHelper::getFastPropertyValue(Any& _rValue, sal_Int32 _nHandle) const
435 {
436 	// get the property somebody is asking for
437 	PropertiesIterator aPos = const_cast<OPropertyContainerHelper*>(this)->searchHandle(_nHandle);
438 	if (aPos == m_aProperties.end())
439 	{
440 		OSL_ENSURE( false, "OPropertyContainerHelper::getFastPropertyValue: unknown handle!" );
441 		// should not happen if the derived class has built a correct property set info helper to be used by
442 		// our base class OPropertySetHelper
443 		return;
444 	}
445 
446 	switch (aPos->eLocated)
447 	{
448 		case PropertyDescription::ltHoldMyself:
449 			OSL_ENSURE(aPos->aLocation.nOwnClassVectorIndex < (sal_Int32)m_aHoldProperties.size(),
450 				"OPropertyContainerHelper::convertFastPropertyValue: invalid position !");
451 			_rValue = m_aHoldProperties[aPos->aLocation.nOwnClassVectorIndex];
452 			break;
453 		case PropertyDescription::ltDerivedClassAnyType:
454 			_rValue = *reinterpret_cast<Any*>(aPos->aLocation.pDerivedClassMember);
455 			break;
456 		case PropertyDescription::ltDerivedClassRealType:
457 			_rValue.setValue(aPos->aLocation.pDerivedClassMember, aPos->aProperty.Type);
458 			break;
459 	}
460 }
461 
462 //--------------------------------------------------------------------------
searchHandle(sal_Int32 _nHandle)463 OPropertyContainerHelper::PropertiesIterator OPropertyContainerHelper::searchHandle(sal_Int32 _nHandle)
464 {
465 	// search a lower bound
466 	PropertiesIterator aLowerBound = ::std::lower_bound(
467 		m_aProperties.begin(),
468 		m_aProperties.end(),
469 		_nHandle,
470 		PropertyDescriptionHandleCompare());
471 
472 	// check for identity
473 	if ((aLowerBound != m_aProperties.end()) && aLowerBound->aProperty.Handle != _nHandle)
474 		aLowerBound = m_aProperties.end();
475 
476 	return aLowerBound;
477 }
478 
479 //--------------------------------------------------------------------------
getProperty(const::rtl::OUString & _rName) const480 const Property& OPropertyContainerHelper::getProperty( const ::rtl::OUString& _rName ) const
481 {
482     ConstPropertiesIterator pos = ::std::find_if(
483         m_aProperties.begin(),
484         m_aProperties.end(),
485         PropertyDescriptionNameMatch( _rName )
486     );
487     if ( pos == m_aProperties.end() )
488         throw UnknownPropertyException( _rName, NULL );
489 
490     return pos->aProperty;
491 }
492 
493 //--------------------------------------------------------------------------
modifyAttributes(sal_Int32 _nHandle,sal_Int32 _nAddAttrib,sal_Int32 _nRemoveAttrib)494 void OPropertyContainerHelper::modifyAttributes(sal_Int32 _nHandle, sal_Int32 _nAddAttrib, sal_Int32 _nRemoveAttrib)
495 {
496 	// get the property somebody is asking for
497 	PropertiesIterator aPos = searchHandle(_nHandle);
498 	if (aPos == m_aProperties.end())
499 	{
500 		OSL_ENSURE( false, "OPropertyContainerHelper::modifyAttributes: unknown handle!" );
501 		// should not happen if the derived class has built a correct property set info helper to be used by
502 		// our base class OPropertySetHelper
503 		return;
504 	}
505 	aPos->aProperty.Handle |= _nAddAttrib;
506 	aPos->aProperty.Handle &= ~_nRemoveAttrib;
507 }
508 
509 //--------------------------------------------------------------------------
describeProperties(Sequence<Property> & _rProps) const510 void OPropertyContainerHelper::describeProperties(Sequence< Property >& _rProps) const
511 {
512 	Sequence< Property > aOwnProps(m_aProperties.size());
513 	Property* pOwnProps = aOwnProps.getArray();
514 
515 	for	(	ConstPropertiesIterator aLoop = m_aProperties.begin();
516 			aLoop != m_aProperties.end();
517 			++aLoop, ++pOwnProps
518 		)
519 	{
520 		pOwnProps->Name = aLoop->aProperty.Name;
521 		pOwnProps->Handle = aLoop->aProperty.Handle;
522 		pOwnProps->Attributes = (sal_Int16)aLoop->aProperty.Attributes;
523 		pOwnProps->Type = aLoop->aProperty.Type;
524 	}
525 
526 	// as our property vector is sorted by handles, not by name, we have to sort aOwnProps
527 	::std::sort(aOwnProps.getArray(), aOwnProps.getArray() + aOwnProps.getLength(), PropertyCompareByName());
528 
529 	// unfortunally the STL merge function does not allow the output range to overlap one of the input ranges,
530 	// so we need an extra sequence
531 	Sequence< Property > aOutput;
532 	aOutput.realloc(_rProps.getLength() + aOwnProps.getLength());
533 	// do the merge
534 	::std::merge(	_rProps.getConstArray(), _rProps.getConstArray() + _rProps.getLength(),			// input 1
535 					aOwnProps.getConstArray(), aOwnProps.getConstArray() + aOwnProps.getLength(),	// input 2
536 					aOutput.getArray(),																// output
537 					PropertyCompareByName()															// compare operator
538 				);
539 
540 	// copy the output
541 	_rProps = aOutput;
542 }
543 
544 //.........................................................................
545 }	// namespace comphelper
546 //.........................................................................
547 
548 
549