/src/libreoffice/comphelper/source/property/propertycontainerhelper.cxx
Line | Count | Source (jump to first uncovered line) |
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 | | #include <comphelper/propertycontainerhelper.hxx> |
21 | | #include <comphelper/property.hxx> |
22 | | #include <osl/diagnose.h> |
23 | | #include <uno/data.h> |
24 | | #include <com/sun/star/uno/Sequence.hxx> |
25 | | #include <com/sun/star/beans/PropertyAttribute.hpp> |
26 | | #include <com/sun/star/beans/UnknownPropertyException.hpp> |
27 | | |
28 | | #include <algorithm> |
29 | | #include <utility> |
30 | | |
31 | | |
32 | | namespace comphelper |
33 | | { |
34 | | |
35 | | |
36 | | using namespace ::com::sun::star::uno; |
37 | | using namespace ::com::sun::star::lang; |
38 | | using namespace ::com::sun::star::beans; |
39 | | |
40 | | |
41 | | namespace |
42 | | { |
43 | | // comparing two property descriptions |
44 | | struct PropertyDescriptionHandleCompare |
45 | | { |
46 | | bool operator() (const PropertyDescription& x, const PropertyDescription& y) const |
47 | 1.55G | { |
48 | 1.55G | return x.aProperty.Handle < y.aProperty.Handle; |
49 | 1.55G | } |
50 | | }; |
51 | | // comparing two property descriptions (by name) |
52 | | struct PropertyDescriptionNameMatch |
53 | | { |
54 | | OUString const m_rCompare; |
55 | 64.1k | explicit PropertyDescriptionNameMatch( OUString _aCompare ) : m_rCompare(std::move( _aCompare )) { } |
56 | | |
57 | | bool operator() (const PropertyDescription& x ) const |
58 | 224k | { |
59 | 224k | return x.aProperty.Name == m_rCompare; |
60 | 224k | } |
61 | | }; |
62 | | } |
63 | | |
64 | | OPropertyContainerHelper::OPropertyContainerHelper() |
65 | 3.66M | { |
66 | 3.66M | } |
67 | | |
68 | | |
69 | | OPropertyContainerHelper::~OPropertyContainerHelper() |
70 | 3.65M | { |
71 | 3.65M | } |
72 | | |
73 | | |
74 | | void OPropertyContainerHelper::registerProperty(const OUString& _rName, sal_Int32 _nHandle, |
75 | | sal_Int32 _nAttributes, void* _pPointerToMember, const Type& _rMemberType) |
76 | 54.0M | { |
77 | 54.0M | OSL_ENSURE((_nAttributes & PropertyAttribute::MAYBEVOID) == 0, |
78 | 54.0M | "OPropertyContainerHelper::registerProperty: don't use this for properties which may be void ! There is a method called \"registerMayBeVoidProperty\" for this !"); |
79 | 54.0M | OSL_ENSURE(!_rMemberType.equals(cppu::UnoType<Any>::get()), |
80 | 54.0M | "OPropertyContainerHelper::registerProperty: don't give my the type of a uno::Any ! Really can't handle this !"); |
81 | 54.0M | OSL_ENSURE(_pPointerToMember, |
82 | 54.0M | "OPropertyContainerHelper::registerProperty: you gave me nonsense : the pointer must be non-NULL"); |
83 | | |
84 | 54.0M | PropertyDescription aNewProp; |
85 | 54.0M | aNewProp.aProperty = Property( _rName, _nHandle, _rMemberType, static_cast<sal_Int16>(_nAttributes) ); |
86 | 54.0M | aNewProp.eLocated = PropertyDescription::LocationType::DerivedClassRealType; |
87 | 54.0M | aNewProp.aLocation.pDerivedClassMember = _pPointerToMember; |
88 | | |
89 | 54.0M | implPushBackProperty(aNewProp); |
90 | 54.0M | } |
91 | | |
92 | | |
93 | | void OPropertyContainerHelper::revokeProperty( sal_Int32 _nHandle ) |
94 | 0 | { |
95 | 0 | PropertiesIterator aPos = searchHandle( _nHandle ); |
96 | 0 | if ( aPos == m_aProperties.end() ) |
97 | 0 | throw UnknownPropertyException(OUString::number(_nHandle)); |
98 | 0 | m_aProperties.erase( aPos ); |
99 | 0 | } |
100 | | |
101 | | |
102 | | void OPropertyContainerHelper::registerMayBeVoidProperty(const OUString& _rName, sal_Int32 _nHandle, sal_Int32 _nAttributes, |
103 | | Any* _pPointerToMember, const Type& _rExpectedType) |
104 | 2.88M | { |
105 | 2.88M | OSL_ENSURE((_nAttributes & PropertyAttribute::MAYBEVOID) != 0, |
106 | 2.88M | "OPropertyContainerHelper::registerMayBeVoidProperty: why calling this when the attributes say nothing about may-be-void ?"); |
107 | 2.88M | OSL_ENSURE(!_rExpectedType.equals(cppu::UnoType<Any>::get()), |
108 | 2.88M | "OPropertyContainerHelper::registerMayBeVoidProperty: don't give my the type of a uno::Any ! Really can't handle this !"); |
109 | 2.88M | OSL_ENSURE(_pPointerToMember, |
110 | 2.88M | "OPropertyContainerHelper::registerMayBeVoidProperty: you gave me nonsense : the pointer must be non-NULL"); |
111 | | |
112 | 2.88M | _nAttributes |= PropertyAttribute::MAYBEVOID; |
113 | | |
114 | 2.88M | PropertyDescription aNewProp; |
115 | 2.88M | aNewProp.aProperty = Property( _rName, _nHandle, _rExpectedType, static_cast<sal_Int16>(_nAttributes) ); |
116 | 2.88M | aNewProp.eLocated = PropertyDescription::LocationType::DerivedClassAnyType; |
117 | 2.88M | aNewProp.aLocation.pDerivedClassMember = _pPointerToMember; |
118 | | |
119 | 2.88M | implPushBackProperty(aNewProp); |
120 | 2.88M | } |
121 | | |
122 | | |
123 | | void OPropertyContainerHelper::registerPropertyNoMember(const OUString& _rName, sal_Int32 _nHandle, sal_Int32 _nAttributes, |
124 | | const Type& _rType, css::uno::Any const & _pInitialValue) |
125 | 80.0k | { |
126 | 80.0k | OSL_ENSURE(!_rType.equals(cppu::UnoType<Any>::get()), |
127 | 80.0k | "OPropertyContainerHelper::registerPropertyNoMember : don't give my the type of a uno::Any ! Really can't handle this !"); |
128 | 80.0k | OSL_ENSURE( |
129 | 80.0k | (_pInitialValue.isExtractableTo(_rType) |
130 | 80.0k | || (!_pInitialValue.hasValue() |
131 | 80.0k | && (_nAttributes & PropertyAttribute::MAYBEVOID) != 0)), |
132 | 80.0k | "bad initial value"); |
133 | | |
134 | 80.0k | PropertyDescription aNewProp; |
135 | 80.0k | aNewProp.aProperty = Property( _rName, _nHandle, _rType, static_cast<sal_Int16>(_nAttributes) ); |
136 | 80.0k | aNewProp.eLocated = PropertyDescription::LocationType::HoldMyself; |
137 | 80.0k | aNewProp.aLocation.nOwnClassVectorIndex = m_aHoldProperties.size(); |
138 | 80.0k | m_aHoldProperties.push_back(_pInitialValue); |
139 | | |
140 | 80.0k | implPushBackProperty(aNewProp); |
141 | 80.0k | } |
142 | | |
143 | | |
144 | | bool OPropertyContainerHelper::isRegisteredProperty( sal_Int32 _nHandle ) const |
145 | 10.4M | { |
146 | 10.4M | return const_cast< OPropertyContainerHelper* >( this )->searchHandle( _nHandle ) != m_aProperties.end(); |
147 | 10.4M | } |
148 | | |
149 | | |
150 | | bool OPropertyContainerHelper::isRegisteredProperty( const OUString& _rName ) const |
151 | 64.1k | { |
152 | | // TODO: the current structure is from a time where properties were |
153 | | // static, not dynamic. Since we allow that properties are also dynamic, |
154 | | // i.e. registered and revoked even though the XPropertySet has already been |
155 | | // accessed, a vector is not really the best data structure anymore ... |
156 | | |
157 | 64.1k | return std::any_of( |
158 | 64.1k | m_aProperties.begin(), |
159 | 64.1k | m_aProperties.end(), |
160 | 64.1k | PropertyDescriptionNameMatch( _rName ) |
161 | 64.1k | ); |
162 | 64.1k | } |
163 | | |
164 | | |
165 | | namespace |
166 | | { |
167 | | struct ComparePropertyHandles |
168 | | { |
169 | | bool operator()( const PropertyDescription& _rLHS, const PropertyDescription& _nRHS ) const |
170 | 157M | { |
171 | 157M | return _rLHS.aProperty.Handle < _nRHS.aProperty.Handle; |
172 | 157M | } |
173 | | }; |
174 | | } |
175 | | |
176 | | |
177 | | void OPropertyContainerHelper::implPushBackProperty(const PropertyDescription& _rProp) |
178 | 57.0M | { |
179 | | #ifdef DBG_UTIL |
180 | | for (const auto& checkConflicts : m_aProperties) |
181 | | { |
182 | | OSL_ENSURE(checkConflicts.aProperty.Name != _rProp.aProperty.Name, "OPropertyContainerHelper::implPushBackProperty: name already exists!"); |
183 | | OSL_ENSURE(checkConflicts.aProperty.Handle != _rProp.aProperty.Handle, "OPropertyContainerHelper::implPushBackProperty: handle already exists!"); |
184 | | } |
185 | | #endif |
186 | | |
187 | 57.0M | PropertiesIterator pos = std::lower_bound( |
188 | 57.0M | m_aProperties.begin(), m_aProperties.end(), |
189 | 57.0M | _rProp, ComparePropertyHandles() ); |
190 | | |
191 | 57.0M | m_aProperties.insert( pos, _rProp ); |
192 | 57.0M | } |
193 | | |
194 | | |
195 | | namespace |
196 | | { |
197 | | void lcl_throwIllegalPropertyValueTypeException( const PropertyDescription& _rProperty, const Any& _rValue ) |
198 | 0 | { |
199 | 0 | throw IllegalArgumentException( |
200 | 0 | "The given value cannot be converted to the required property type." |
201 | 0 | " (property name \"" + _rProperty.aProperty.Name |
202 | 0 | + "\", found value type \"" + _rValue.getValueTypeName() |
203 | 0 | + "\", required property type \"" + _rProperty.aProperty.Type.getTypeName() |
204 | 0 | + "\")", |
205 | 0 | nullptr, 4 ); |
206 | 0 | } |
207 | | } |
208 | | |
209 | | |
210 | | bool OPropertyContainerHelper::convertFastPropertyValue( |
211 | | Any& _rConvertedValue, Any& _rOldValue, sal_Int32 _nHandle, const Any& _rValue ) |
212 | 2.84M | { |
213 | 2.84M | bool bModified = false; |
214 | | |
215 | | // get the property somebody is asking for |
216 | 2.84M | PropertiesIterator aPos = searchHandle(_nHandle); |
217 | 2.84M | if (aPos == m_aProperties.end()) |
218 | 0 | { |
219 | 0 | OSL_FAIL( "OPropertyContainerHelper::convertFastPropertyValue: unknown handle!" ); |
220 | | // should not happen if the derived class has built a correct property set info helper to be used by |
221 | | // our base class OPropertySetHelper |
222 | 0 | return bModified; |
223 | 0 | } |
224 | | |
225 | 2.84M | switch (aPos->eLocated) |
226 | 2.84M | { |
227 | | // similar handling for the two cases where the value is stored in an any |
228 | 0 | case PropertyDescription::LocationType::HoldMyself: |
229 | 2.18M | case PropertyDescription::LocationType::DerivedClassAnyType: |
230 | 2.18M | { |
231 | 2.18M | bool bMayBeVoid = ((aPos->aProperty.Attributes & PropertyAttribute::MAYBEVOID) != 0); |
232 | | |
233 | | |
234 | | // non modifiable version of the value-to-be-set |
235 | 2.18M | Any aNewRequestedValue( _rValue ); |
236 | | |
237 | | // normalization |
238 | | // #i29490# |
239 | 2.18M | if ( !aNewRequestedValue.getValueType().equals( aPos->aProperty.Type ) ) |
240 | 1.55M | { // the actually given value is not of the same type as the one required |
241 | 1.55M | Any aProperlyTyped( nullptr, aPos->aProperty.Type.getTypeLibType() ); |
242 | | |
243 | 1.55M | if ( uno_type_assignData( |
244 | 1.55M | const_cast< void* >( aProperlyTyped.getValue() ), aProperlyTyped.getValueType().getTypeLibType(), |
245 | 1.55M | const_cast< void* >( aNewRequestedValue.getValue() ), aNewRequestedValue.getValueType().getTypeLibType(), |
246 | 1.55M | reinterpret_cast< uno_QueryInterfaceFunc >( cpp_queryInterface ), |
247 | 1.55M | reinterpret_cast< uno_AcquireFunc >( cpp_acquire ), |
248 | 1.55M | reinterpret_cast< uno_ReleaseFunc >( cpp_release ) |
249 | 1.55M | ) |
250 | 1.55M | ) |
251 | 0 | { |
252 | | // we were able to query the given XInterface-derivee for the interface |
253 | | // which is required for this property |
254 | 0 | aNewRequestedValue = std::move(aProperlyTyped); |
255 | 0 | } |
256 | 1.55M | } |
257 | | |
258 | | // argument check |
259 | 2.18M | if ( ! ( (bMayBeVoid && !aNewRequestedValue.hasValue()) // void is allowed if the attribute says so |
260 | 2.18M | || (aNewRequestedValue.getValueType().equals(aPos->aProperty.Type)) // else the types have to be equal |
261 | 2.18M | ) |
262 | 2.18M | ) |
263 | 0 | { |
264 | 0 | lcl_throwIllegalPropertyValueTypeException( *aPos, _rValue ); |
265 | 0 | } |
266 | | |
267 | 2.18M | Any* pPropContainer = nullptr; |
268 | | // the pointer to the any which holds the property value, no matter if located in the derived class |
269 | | // or in out vector |
270 | | |
271 | 2.18M | if (PropertyDescription::LocationType::HoldMyself == aPos->eLocated) |
272 | 0 | { |
273 | 0 | OSL_ENSURE(aPos->aLocation.nOwnClassVectorIndex < m_aHoldProperties.size(), |
274 | 0 | "OPropertyContainerHelper::convertFastPropertyValue: invalid position !"); |
275 | 0 | auto aIter = m_aHoldProperties.begin() + aPos->aLocation.nOwnClassVectorIndex; |
276 | 0 | pPropContainer = &(*aIter); |
277 | 0 | } |
278 | 2.18M | else |
279 | 2.18M | pPropContainer = static_cast<Any*>(aPos->aLocation.pDerivedClassMember); |
280 | | |
281 | | // check if the new value differs from the current one |
282 | 2.18M | if (!pPropContainer->hasValue() || !aNewRequestedValue.hasValue()) |
283 | 1.86M | bModified = pPropContainer->hasValue() != aNewRequestedValue.hasValue(); |
284 | 320k | else |
285 | 320k | bModified = !uno_type_equalData( |
286 | 320k | const_cast< void* >( pPropContainer->getValue() ), aPos->aProperty.Type.getTypeLibType(), |
287 | 320k | const_cast< void* >( aNewRequestedValue.getValue() ), aPos->aProperty.Type.getTypeLibType(), |
288 | 320k | reinterpret_cast< uno_QueryInterfaceFunc >( cpp_queryInterface ), |
289 | 320k | reinterpret_cast< uno_ReleaseFunc >( cpp_release ) |
290 | 320k | ); |
291 | | |
292 | 2.18M | if (bModified) |
293 | 320k | { |
294 | 320k | _rOldValue = *pPropContainer; |
295 | 320k | _rConvertedValue = std::move(aNewRequestedValue); |
296 | 320k | } |
297 | 2.18M | } |
298 | 2.18M | break; |
299 | 661k | case PropertyDescription::LocationType::DerivedClassRealType: |
300 | | // let the UNO runtime library do any possible conversion |
301 | | // this may include a change of the type - for instance, if a LONG is required, |
302 | | // but a short is given, then this is valid, as it can be converted without any potential |
303 | | // data loss |
304 | | |
305 | 661k | Any aProperlyTyped; |
306 | 661k | const Any* pNewValue = &_rValue; |
307 | | |
308 | 661k | if (!_rValue.getValueType().equals(aPos->aProperty.Type)) |
309 | 0 | { |
310 | 0 | bool bConverted = false; |
311 | | |
312 | | // a temporary any of the correct (required) type |
313 | 0 | aProperlyTyped = Any( nullptr, aPos->aProperty.Type.getTypeLibType() ); |
314 | | // (need this as we do not want to overwrite the derived class member here) |
315 | |
|
316 | 0 | if ( uno_type_assignData( |
317 | 0 | const_cast<void*>(aProperlyTyped.getValue()), aProperlyTyped.getValueType().getTypeLibType(), |
318 | 0 | const_cast<void*>(_rValue.getValue()), _rValue.getValueType().getTypeLibType(), |
319 | 0 | reinterpret_cast< uno_QueryInterfaceFunc >( cpp_queryInterface ), |
320 | 0 | reinterpret_cast< uno_AcquireFunc >( cpp_acquire ), |
321 | 0 | reinterpret_cast< uno_ReleaseFunc >( cpp_release ) |
322 | 0 | ) |
323 | 0 | ) |
324 | 0 | { |
325 | | // could query for the requested interface |
326 | 0 | bConverted = true; |
327 | 0 | pNewValue = &aProperlyTyped; |
328 | 0 | } |
329 | |
|
330 | 0 | if ( !bConverted ) |
331 | 0 | lcl_throwIllegalPropertyValueTypeException( *aPos, _rValue ); |
332 | 0 | } |
333 | | |
334 | | // from here on, we should have the proper type |
335 | 661k | OSL_ENSURE( pNewValue->getValueType() == aPos->aProperty.Type, |
336 | 661k | "OPropertyContainerHelper::convertFastPropertyValue: conversion failed!" ); |
337 | 661k | bModified = !uno_type_equalData( |
338 | 661k | aPos->aLocation.pDerivedClassMember, aPos->aProperty.Type.getTypeLibType(), |
339 | 661k | const_cast<void*>(pNewValue->getValue()), aPos->aProperty.Type.getTypeLibType(), |
340 | 661k | reinterpret_cast< uno_QueryInterfaceFunc >( cpp_queryInterface ), |
341 | 661k | reinterpret_cast< uno_ReleaseFunc >( cpp_release ) |
342 | 661k | ); |
343 | | |
344 | 661k | if (bModified) |
345 | 39.4k | { |
346 | 39.4k | _rOldValue.setValue(aPos->aLocation.pDerivedClassMember, aPos->aProperty.Type); |
347 | 39.4k | _rConvertedValue = *pNewValue; |
348 | 39.4k | } |
349 | 661k | break; |
350 | 2.84M | } |
351 | | |
352 | 2.84M | return bModified; |
353 | 2.84M | } |
354 | | |
355 | | |
356 | | void OPropertyContainerHelper::setFastPropertyValue(sal_Int32 _nHandle, const Any& _rValue) |
357 | 360k | { |
358 | | // get the property somebody is asking for |
359 | 360k | PropertiesIterator aPos = searchHandle(_nHandle); |
360 | 360k | if (aPos == m_aProperties.end()) |
361 | 0 | { |
362 | 0 | OSL_FAIL( "OPropertyContainerHelper::setFastPropertyValue: unknown handle!" ); |
363 | | // should not happen if the derived class has built a correct property set info helper to be used by |
364 | | // our base class OPropertySetHelper |
365 | 0 | return; |
366 | 0 | } |
367 | | |
368 | 360k | bool bSuccess = true; |
369 | | |
370 | 360k | switch (aPos->eLocated) |
371 | 360k | { |
372 | 0 | case PropertyDescription::LocationType::HoldMyself: |
373 | 0 | m_aHoldProperties[aPos->aLocation.nOwnClassVectorIndex] = _rValue; |
374 | 0 | break; |
375 | | |
376 | 320k | case PropertyDescription::LocationType::DerivedClassAnyType: |
377 | 320k | *static_cast< Any* >(aPos->aLocation.pDerivedClassMember) = _rValue; |
378 | 320k | break; |
379 | | |
380 | 39.4k | case PropertyDescription::LocationType::DerivedClassRealType: |
381 | | // copy the data from the to-be-set value |
382 | 39.4k | bSuccess = uno_type_assignData( |
383 | 39.4k | aPos->aLocation.pDerivedClassMember, aPos->aProperty.Type.getTypeLibType(), |
384 | 39.4k | const_cast< void* >( _rValue.getValue() ), _rValue.getValueType().getTypeLibType(), |
385 | 39.4k | reinterpret_cast< uno_QueryInterfaceFunc >( cpp_queryInterface ), |
386 | 39.4k | reinterpret_cast< uno_AcquireFunc >( cpp_acquire ), |
387 | 39.4k | reinterpret_cast< uno_ReleaseFunc >( cpp_release ) ); |
388 | | |
389 | 39.4k | OSL_ENSURE( bSuccess, |
390 | 39.4k | "OPropertyContainerHelper::setFastPropertyValue: ooops... the value could not be assigned!"); |
391 | | |
392 | 39.4k | break; |
393 | 360k | } |
394 | 360k | } |
395 | | |
396 | | void OPropertyContainerHelper::getFastPropertyValue(Any& _rValue, sal_Int32 _nHandle) const |
397 | 352M | { |
398 | | // get the property somebody is asking for |
399 | 352M | PropertiesIterator aPos = const_cast<OPropertyContainerHelper*>(this)->searchHandle(_nHandle); |
400 | 352M | if (aPos == m_aProperties.end()) |
401 | 0 | { |
402 | 0 | assert( false && "OPropertyContainerHelper::getFastPropertyValue: unknown handle" ); |
403 | | // should not happen if the derived class has built a correct property set info helper to be used by |
404 | | // our base class OPropertySetHelper |
405 | 0 | return; |
406 | 0 | } |
407 | | |
408 | 352M | switch (aPos->eLocated) |
409 | 352M | { |
410 | 20.3k | case PropertyDescription::LocationType::HoldMyself: |
411 | 20.3k | OSL_ENSURE(aPos->aLocation.nOwnClassVectorIndex < m_aHoldProperties.size(), |
412 | 20.3k | "OPropertyContainerHelper::convertFastPropertyValue: invalid position !"); |
413 | 20.3k | _rValue = m_aHoldProperties[aPos->aLocation.nOwnClassVectorIndex]; |
414 | 20.3k | break; |
415 | 1.86M | case PropertyDescription::LocationType::DerivedClassAnyType: |
416 | 1.86M | _rValue = *static_cast<Any*>(aPos->aLocation.pDerivedClassMember); |
417 | 1.86M | break; |
418 | 350M | case PropertyDescription::LocationType::DerivedClassRealType: |
419 | 350M | _rValue.setValue(aPos->aLocation.pDerivedClassMember, aPos->aProperty.Type); |
420 | 350M | break; |
421 | 352M | } |
422 | 352M | } |
423 | | |
424 | | |
425 | | OPropertyContainerHelper::PropertiesIterator OPropertyContainerHelper::searchHandle(sal_Int32 _nHandle) |
426 | 365M | { |
427 | 365M | PropertyDescription aHandlePropDesc; |
428 | 365M | aHandlePropDesc.aProperty.Handle = _nHandle; |
429 | | // search a lower bound |
430 | 365M | PropertiesIterator aLowerBound = std::lower_bound( |
431 | 365M | m_aProperties.begin(), |
432 | 365M | m_aProperties.end(), |
433 | 365M | aHandlePropDesc, |
434 | 365M | PropertyDescriptionHandleCompare()); |
435 | | |
436 | | // check for identity |
437 | 365M | if ((aLowerBound != m_aProperties.end()) && aLowerBound->aProperty.Handle != _nHandle) |
438 | 7.47M | aLowerBound = m_aProperties.end(); |
439 | | |
440 | 365M | return aLowerBound; |
441 | 365M | } |
442 | | |
443 | | |
444 | | const Property& OPropertyContainerHelper::getProperty( const OUString& _rName ) const |
445 | 0 | { |
446 | 0 | ConstPropertiesIterator pos = std::find_if( |
447 | 0 | m_aProperties.begin(), |
448 | 0 | m_aProperties.end(), |
449 | 0 | PropertyDescriptionNameMatch( _rName ) |
450 | 0 | ); |
451 | 0 | if ( pos == m_aProperties.end() ) |
452 | 0 | throw UnknownPropertyException( _rName ); |
453 | | |
454 | 0 | return pos->aProperty; |
455 | 0 | } |
456 | | |
457 | | |
458 | | void OPropertyContainerHelper::describeProperties(Sequence< Property >& _rProps) const |
459 | 127k | { |
460 | 127k | Sequence< Property > aOwnProps(m_aProperties.size()); |
461 | 127k | Property* pOwnProps = aOwnProps.getArray(); |
462 | | |
463 | 127k | for (const auto& rProp : m_aProperties) |
464 | 1.95M | { |
465 | 1.95M | pOwnProps->Name = rProp.aProperty.Name; |
466 | 1.95M | pOwnProps->Handle = rProp.aProperty.Handle; |
467 | 1.95M | pOwnProps->Attributes = rProp.aProperty.Attributes; |
468 | 1.95M | pOwnProps->Type = rProp.aProperty.Type; |
469 | 1.95M | ++pOwnProps; |
470 | 1.95M | } |
471 | | |
472 | | // as our property vector is sorted by handles, not by name, we have to sort aOwnProps |
473 | 127k | auto [begin, end] = asNonConstRange(aOwnProps); |
474 | 127k | std::sort(begin, end, PropertyCompareByName()); |
475 | | |
476 | | // unfortunately the STL merge function does not allow the output range to overlap one of the input ranges, |
477 | | // so we need an extra sequence |
478 | 127k | Sequence< Property > aOutput(_rProps.getLength() + aOwnProps.getLength()); |
479 | | // do the merge |
480 | 127k | std::merge( std::cbegin(_rProps), std::cend(_rProps), // input 1 |
481 | 127k | std::cbegin(aOwnProps), std::cend(aOwnProps), // input 2 |
482 | 127k | aOutput.getArray(), // output |
483 | 127k | PropertyCompareByName() // compare operator |
484 | 127k | ); |
485 | | |
486 | | // copy the output |
487 | 127k | _rProps = std::move(aOutput); |
488 | 127k | } |
489 | | |
490 | | |
491 | | } // namespace comphelper |
492 | | |
493 | | |
494 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |