/src/libreoffice/xmloff/source/style/xmlprmap.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 <o3tl/safeint.hxx> |
21 | | #include <rtl/ref.hxx> |
22 | | |
23 | | #include <xmloff/xmlprmap.hxx> |
24 | | #include <xmloff/xmlprhdl.hxx> |
25 | | #include <xmloff/xmltypes.hxx> |
26 | | #include <xmloff/xmltoken.hxx> |
27 | | #include <xmloff/maptype.hxx> |
28 | | #include <xmloff/prhdlfac.hxx> |
29 | | #include <xmloff/xmlimp.hxx> |
30 | | |
31 | | #include <vector> |
32 | | |
33 | | using ::xmloff::token::GetXMLToken; |
34 | | |
35 | | namespace { |
36 | | |
37 | | /** Helper-class for XML-im/export: |
38 | | - Holds a pointer to a given array of XMLPropertyMapEntry |
39 | | - Provides several methods to access data from this array |
40 | | - Holds a Sequence of XML-names (for properties) |
41 | | - The filter takes all properties of the XPropertySet which are also |
42 | | in the XMLPropertyMapEntry and which are have not a default value |
43 | | and put them into a vector of XMLPropertyStae |
44 | | - this class knows how to compare, im/export properties |
45 | | |
46 | | Attention: At all methods, which get an index as parameter, there is no |
47 | | range validation to save runtime !! |
48 | | */ |
49 | | struct XMLPropertySetMapperEntry_Impl |
50 | | { |
51 | | OUString sXMLAttributeName; |
52 | | OUString sAPIPropertyName; |
53 | | sal_Int32 nType; |
54 | | sal_uInt16 nXMLNameSpace; |
55 | | sal_Int16 nContextId; |
56 | | SvtSaveOptions::ODFSaneDefaultVersion nEarliestODFVersionForExport; |
57 | | bool bImportOnly; |
58 | | const XMLPropertyHandler *pHdl; |
59 | | |
60 | | XMLPropertySetMapperEntry_Impl( |
61 | | const XMLPropertyMapEntry& rMapEntry, |
62 | | const rtl::Reference< XMLPropertyHandlerFactory >& rFactory ); |
63 | | |
64 | 216M | sal_uInt32 GetPropType() const { return nType & XML_TYPE_PROP_MASK; } |
65 | | }; |
66 | | |
67 | | } |
68 | | |
69 | | XMLPropertySetMapperEntry_Impl::XMLPropertySetMapperEntry_Impl( |
70 | | const XMLPropertyMapEntry& rMapEntry, |
71 | | const rtl::Reference< XMLPropertyHandlerFactory >& rFactory ) : |
72 | 64.1M | sXMLAttributeName( GetXMLToken(rMapEntry.meXMLName) ), |
73 | 64.1M | sAPIPropertyName( rMapEntry.getApiName() ), |
74 | 64.1M | nType( rMapEntry.mnType ), |
75 | 64.1M | nXMLNameSpace( rMapEntry.mnNameSpace ), |
76 | 64.1M | nContextId( rMapEntry.mnContextId ), |
77 | 64.1M | nEarliestODFVersionForExport( rMapEntry.mnEarliestODFVersionForExport ), |
78 | 64.1M | bImportOnly( rMapEntry.mbImportOnly), |
79 | 64.1M | pHdl( rFactory->GetPropertyHandler( rMapEntry.mnType & MID_FLAG_MASK ) ) |
80 | 64.1M | { |
81 | 64.1M | assert(pHdl); |
82 | 64.1M | } |
83 | | |
84 | | struct XMLPropertySetMapper::Impl |
85 | | { |
86 | | std::vector<XMLPropertySetMapperEntry_Impl> maMapEntries; |
87 | | std::vector<rtl::Reference <XMLPropertyHandlerFactory> > maHdlFactories; |
88 | | |
89 | | bool mbOnlyExportMappings; |
90 | | |
91 | 711k | explicit Impl( bool bForExport ) : mbOnlyExportMappings(bForExport) {} |
92 | | }; |
93 | | |
94 | | // Ctor |
95 | | XMLPropertySetMapper::XMLPropertySetMapper( |
96 | | const XMLPropertyMapEntry* pEntries, const rtl::Reference<XMLPropertyHandlerFactory>& rFactory, |
97 | | bool bForExport ) : |
98 | 711k | mpImpl(new Impl(bForExport)) |
99 | 711k | { |
100 | 711k | mpImpl->maHdlFactories.push_back(rFactory); |
101 | 711k | if( !pEntries ) |
102 | 0 | return; |
103 | | |
104 | 711k | const XMLPropertyMapEntry* pIter = pEntries; |
105 | | |
106 | 711k | if (mpImpl->mbOnlyExportMappings) |
107 | 3.37k | { |
108 | 47.1k | while( !pIter->IsEnd() ) |
109 | 43.8k | { |
110 | 43.8k | if (!pIter->mbImportOnly) |
111 | 43.8k | { |
112 | 43.8k | XMLPropertySetMapperEntry_Impl aEntry( *pIter, rFactory ); |
113 | 43.8k | mpImpl->maMapEntries.push_back( aEntry ); |
114 | 43.8k | } |
115 | 43.8k | ++pIter; |
116 | 43.8k | } |
117 | 3.37k | } |
118 | 708k | else |
119 | 708k | { |
120 | 64.8M | while( !pIter->IsEnd() ) |
121 | 64.1M | { |
122 | 64.1M | XMLPropertySetMapperEntry_Impl aEntry( *pIter, rFactory ); |
123 | 64.1M | mpImpl->maMapEntries.push_back( aEntry ); |
124 | 64.1M | ++pIter; |
125 | 64.1M | } |
126 | 708k | } |
127 | 711k | } |
128 | | |
129 | | XMLPropertySetMapper::~XMLPropertySetMapper() |
130 | 711k | { |
131 | 711k | } |
132 | | |
133 | | void XMLPropertySetMapper::AddMapperEntry( |
134 | | const rtl::Reference < XMLPropertySetMapper >& rMapper ) |
135 | 145k | { |
136 | 145k | for( const auto& rHdlFactory : rMapper->mpImpl->maHdlFactories ) |
137 | 185k | { |
138 | 185k | mpImpl->maHdlFactories.push_back(rHdlFactory); |
139 | 185k | } |
140 | | |
141 | 145k | for( const auto& rMapEntry : rMapper->mpImpl->maMapEntries ) |
142 | 21.6M | { |
143 | 21.6M | if (!mpImpl->mbOnlyExportMappings || !rMapEntry.bImportOnly) |
144 | 21.6M | mpImpl->maMapEntries.push_back( rMapEntry ); |
145 | 21.6M | } |
146 | 145k | } |
147 | | |
148 | | sal_Int32 XMLPropertySetMapper::GetEntryCount() const |
149 | 9.10M | { |
150 | 9.10M | return mpImpl->maMapEntries.size(); |
151 | 9.10M | } |
152 | | |
153 | | sal_uInt32 XMLPropertySetMapper::GetEntryFlags( sal_Int32 nIndex ) const |
154 | 2.87M | { |
155 | 2.87M | assert((0 <= nIndex) && (o3tl::make_unsigned(nIndex) < mpImpl->maMapEntries.size())); |
156 | 2.87M | return mpImpl->maMapEntries[nIndex].nType & ~MID_FLAG_MASK; |
157 | 2.87M | } |
158 | | |
159 | | sal_uInt32 XMLPropertySetMapper::GetEntryType( sal_Int32 nIndex ) const |
160 | 0 | { |
161 | 0 | assert((0 <= nIndex) && (o3tl::make_unsigned(nIndex) < mpImpl->maMapEntries.size())); |
162 | 0 | sal_uInt32 nType = mpImpl->maMapEntries[nIndex].nType; |
163 | 0 | return nType; |
164 | 0 | } |
165 | | |
166 | | sal_uInt16 XMLPropertySetMapper::GetEntryNameSpace( sal_Int32 nIndex ) const |
167 | 0 | { |
168 | 0 | assert((0 <= nIndex) && (o3tl::make_unsigned(nIndex) < mpImpl->maMapEntries.size())); |
169 | 0 | return mpImpl->maMapEntries[nIndex].nXMLNameSpace; |
170 | 0 | } |
171 | | |
172 | | const OUString& XMLPropertySetMapper::GetEntryXMLName( sal_Int32 nIndex ) const |
173 | 0 | { |
174 | 0 | assert((0 <= nIndex) && (o3tl::make_unsigned(nIndex) < mpImpl->maMapEntries.size())); |
175 | 0 | return mpImpl->maMapEntries[nIndex].sXMLAttributeName; |
176 | 0 | } |
177 | | |
178 | | const OUString& XMLPropertySetMapper::GetEntryAPIName( sal_Int32 nIndex ) const |
179 | 26.3M | { |
180 | 26.3M | assert((0 <= nIndex) && (o3tl::make_unsigned(nIndex) < mpImpl->maMapEntries.size())); |
181 | 26.3M | return mpImpl->maMapEntries[nIndex].sAPIPropertyName; |
182 | 26.3M | } |
183 | | |
184 | | sal_Int16 XMLPropertySetMapper::GetEntryContextId( sal_Int32 nIndex ) const |
185 | 16.6M | { |
186 | 16.6M | assert((-1 <= nIndex) && (nIndex < static_cast<sal_Int32>(mpImpl->maMapEntries.size()))); |
187 | 16.6M | return nIndex == -1 ? 0 : mpImpl->maMapEntries[nIndex].nContextId; |
188 | 16.6M | } |
189 | | |
190 | | SvtSaveOptions::ODFSaneDefaultVersion |
191 | | XMLPropertySetMapper::GetEarliestODFVersionForExport(sal_Int32 const nIndex) const |
192 | 0 | { |
193 | 0 | assert((0 <= nIndex) && (o3tl::make_unsigned(nIndex) < mpImpl->maMapEntries.size())); |
194 | 0 | return mpImpl->maMapEntries[nIndex].nEarliestODFVersionForExport; |
195 | 0 | } |
196 | | |
197 | | const XMLPropertyHandler* XMLPropertySetMapper::GetPropertyHandler( sal_Int32 nIndex ) const |
198 | 1.30M | { |
199 | 1.30M | assert((0 <= nIndex) && (o3tl::make_unsigned(nIndex) < mpImpl->maMapEntries.size())); |
200 | 1.30M | return mpImpl->maMapEntries[nIndex].pHdl; |
201 | 1.30M | } |
202 | | |
203 | | // Export a Property |
204 | | bool XMLPropertySetMapper::exportXML( |
205 | | OUString& rStrExpValue, |
206 | | const XMLPropertyState& rProperty, |
207 | | const SvXMLUnitConverter& rUnitConverter ) const |
208 | 0 | { |
209 | 0 | bool bRet = false; |
210 | |
|
211 | 0 | const XMLPropertyHandler* pHdl = GetPropertyHandler( rProperty.mnIndex ); |
212 | |
|
213 | 0 | assert(pHdl); |
214 | 0 | if( pHdl ) |
215 | 0 | bRet = pHdl->exportXML( rStrExpValue, rProperty.maValue, |
216 | 0 | rUnitConverter ); |
217 | |
|
218 | 0 | return bRet; |
219 | 0 | } |
220 | | |
221 | | // Import a Property |
222 | | bool XMLPropertySetMapper::importXML( |
223 | | const OUString& rStrImpValue, |
224 | | XMLPropertyState& rProperty, |
225 | | const SvXMLUnitConverter& rUnitConverter ) const |
226 | 1.30M | { |
227 | 1.30M | bool bRet = false; |
228 | | |
229 | 1.30M | const XMLPropertyHandler* pHdl = GetPropertyHandler( rProperty.mnIndex ); |
230 | | |
231 | 1.30M | if( pHdl ) |
232 | 1.30M | bRet = pHdl->importXML( rStrImpValue, rProperty.maValue, |
233 | 1.30M | rUnitConverter ); |
234 | | |
235 | 1.30M | return bRet; |
236 | 1.30M | } |
237 | | |
238 | | // Search for the given name and the namespace in the list and return |
239 | | // the index of the entry |
240 | | // If there is no matching entry the method returns -1 |
241 | | sal_Int32 XMLPropertySetMapper::GetEntryIndex( |
242 | | sal_uInt16 nNamespace, |
243 | | std::u16string_view rStrName, |
244 | | sal_uInt32 nPropType, |
245 | | sal_Int32 nStartAt /* = -1 */ ) const |
246 | 1.72M | { |
247 | 1.72M | sal_Int32 nEntries = GetEntryCount(); |
248 | 1.72M | sal_Int32 nIndex= nStartAt == - 1? 0 : nStartAt+1; |
249 | | |
250 | 1.72M | if ( nEntries && nIndex < nEntries ) |
251 | 1.72M | { |
252 | 1.72M | do |
253 | 212M | { |
254 | 212M | const XMLPropertySetMapperEntry_Impl& rEntry = mpImpl->maMapEntries[nIndex]; |
255 | 212M | if( (!nPropType || nPropType == rEntry.GetPropType()) && |
256 | 212M | rEntry.nXMLNameSpace == nNamespace && |
257 | 212M | rStrName == rEntry.sXMLAttributeName ) |
258 | 1.39M | return nIndex; |
259 | 210M | else |
260 | 210M | nIndex++; |
261 | | |
262 | 212M | } while( nIndex<nEntries ); |
263 | 1.72M | } |
264 | | |
265 | 336k | return -1; |
266 | 1.72M | } |
267 | | |
268 | | // Search for the given name and the namespace in the list and return |
269 | | // the index of the entry |
270 | | // If there is no matching entry the method returns -1 |
271 | | sal_Int32 XMLPropertySetMapper::GetEntryIndex( |
272 | | sal_Int32 nElement, |
273 | | sal_uInt32 nPropType, |
274 | | sal_Int32 nStartAt /* = -1 */ ) const |
275 | 22.3k | { |
276 | 22.3k | sal_Int32 nEntries = GetEntryCount(); |
277 | 22.3k | sal_Int32 nIndex= nStartAt == - 1? 0 : nStartAt+1; |
278 | | |
279 | 22.3k | if ( nEntries && nIndex < nEntries ) |
280 | 22.3k | { |
281 | 22.3k | sal_uInt16 nNamespace = (nElement >> NMSP_SHIFT) - 1; |
282 | 22.3k | const OUString& rStrName = SvXMLImport::getNameFromToken(nElement); |
283 | 22.3k | do |
284 | 4.35M | { |
285 | 4.35M | const XMLPropertySetMapperEntry_Impl& rEntry = mpImpl->maMapEntries[nIndex]; |
286 | 4.35M | if( (!nPropType || nPropType == rEntry.GetPropType()) && |
287 | 4.35M | rEntry.nXMLNameSpace == nNamespace && |
288 | 4.35M | rStrName == rEntry.sXMLAttributeName ) |
289 | 19.8k | return nIndex; |
290 | 4.34M | else |
291 | 4.34M | nIndex++; |
292 | | |
293 | 4.35M | } while( nIndex<nEntries ); |
294 | 22.3k | } |
295 | | |
296 | 2.55k | return -1; |
297 | 22.3k | } |
298 | | |
299 | | /** searches for an entry that matches the given api name, namespace and local name or -1 if nothing found */ |
300 | | sal_Int32 XMLPropertySetMapper::FindEntryIndex( |
301 | | const char* sApiName, |
302 | | sal_uInt16 nNameSpace, |
303 | | std::u16string_view sXMLName ) const |
304 | 101k | { |
305 | 101k | sal_Int32 nIndex = 0; |
306 | 101k | sal_Int32 nEntries = GetEntryCount(); |
307 | | |
308 | 101k | do |
309 | 14.7M | { |
310 | 14.7M | const XMLPropertySetMapperEntry_Impl& rEntry = mpImpl->maMapEntries[nIndex]; |
311 | 14.7M | if( rEntry.nXMLNameSpace == nNameSpace && |
312 | 14.7M | rEntry.sXMLAttributeName == sXMLName && |
313 | 14.7M | rEntry.sAPIPropertyName.equalsAscii( sApiName ) ) |
314 | 45.1k | return nIndex; |
315 | 14.7M | else |
316 | 14.7M | nIndex++; |
317 | | |
318 | 14.7M | } while( nIndex < nEntries ); |
319 | | |
320 | 56.1k | return -1; |
321 | 101k | } |
322 | | |
323 | | sal_Int32 XMLPropertySetMapper::FindEntryIndex( const sal_Int16 nContextId ) const |
324 | 59.5k | { |
325 | 59.5k | const sal_Int32 nEntries = GetEntryCount(); |
326 | | |
327 | 59.5k | if ( nEntries ) |
328 | 59.5k | { |
329 | 59.5k | sal_Int32 nIndex = 0; |
330 | 59.5k | do |
331 | 6.28M | { |
332 | 6.28M | const XMLPropertySetMapperEntry_Impl& rEntry = mpImpl->maMapEntries[nIndex]; |
333 | 6.28M | if( rEntry.nContextId == nContextId ) |
334 | 59.0k | return nIndex; |
335 | 6.22M | else |
336 | 6.22M | nIndex++; |
337 | | |
338 | 6.28M | } while( nIndex < nEntries ); |
339 | 59.5k | } |
340 | | |
341 | 408 | return -1; |
342 | 59.5k | } |
343 | | |
344 | | void XMLPropertySetMapper::RemoveEntry( sal_Int32 nIndex ) |
345 | 126 | { |
346 | 126 | const sal_Int32 nEntries = GetEntryCount(); |
347 | 126 | if( nIndex>=nEntries || nIndex<0 ) |
348 | 0 | return; |
349 | 126 | std::vector < XMLPropertySetMapperEntry_Impl >::iterator aEIter = mpImpl->maMapEntries.begin(); |
350 | 126 | std::advance(aEIter, nIndex); |
351 | 126 | mpImpl->maMapEntries.erase( aEIter ); |
352 | 126 | } |
353 | | |
354 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |