Coverage Report

Created: 2025-07-07 10:01

/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: */