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