Coverage Report

Created: 2026-05-16 09:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/sax/source/tools/fastattribs.cxx
Line
Count
Source
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 <algorithm>
21
22
#include <com/sun/star/xml/sax/SAXException.hpp>
23
#include <sax/fastattribs.hxx>
24
#include <utility>
25
26
using namespace ::com::sun::star::uno;
27
using namespace ::com::sun::star::xml;
28
using namespace ::com::sun::star::xml::sax;
29
namespace sax_fastparser
30
{
31
32
// wastage to keep MSVC happy vs. an in-line {}
33
FastTokenHandlerBase::~FastTokenHandlerBase()
34
194k
{
35
194k
}
36
37
UnknownAttribute::UnknownAttribute( OUString aNamespaceURL, OString aName, OString value )
38
1.18M
    : maNamespaceURL(std::move( aNamespaceURL )), maName(std::move( aName )), maValue(std::move( value ))
39
1.18M
{
40
1.18M
}
41
42
UnknownAttribute::UnknownAttribute( OString aName, OString value )
43
1.51M
    : maName(std::move( aName )), maValue(std::move( value ))
44
1.51M
{
45
1.51M
}
46
47
void UnknownAttribute::FillAttribute( Attribute* pAttrib ) const
48
1.34M
{
49
1.34M
    if( pAttrib )
50
1.34M
    {
51
1.34M
        pAttrib->Name = OStringToOUString( maName, RTL_TEXTENCODING_UTF8 );
52
1.34M
        pAttrib->NamespaceURL = maNamespaceURL;
53
1.34M
        pAttrib->Value = OStringToOUString( maValue, RTL_TEXTENCODING_UTF8 );
54
1.34M
    }
55
1.34M
}
56
57
FastAttributeList::FastAttributeList( sax_fastparser::FastTokenHandlerBase *pTokenHandler)
58
288k
: mpTokenHandler( pTokenHandler )
59
288k
{
60
    // random initial size of buffer to store attribute values
61
288k
    mnChunkLength = 58;
62
288k
    mpChunk = static_cast<char *>(malloc( mnChunkLength ));
63
288k
    maAttributeValues.push_back( 0 );
64
288k
}
65
66
FastAttributeList::FastAttributeList( const css::uno::Reference< css::xml::sax::XFastAttributeList > & xAttrList )
67
98.3k
{
68
98.3k
    const auto& rOther = castToFastAttributeList(xAttrList);
69
98.3k
    mpTokenHandler = rOther.mpTokenHandler;
70
98.3k
    mpChunk = static_cast<char *>(malloc( rOther.mnChunkLength ));
71
98.3k
    mnChunkLength = rOther.mnChunkLength;
72
98.3k
    memcpy(mpChunk, rOther.mpChunk, rOther.mnChunkLength);
73
98.3k
    maAttributeValues = rOther.maAttributeValues;
74
98.3k
    maAttributeTokens = rOther.maAttributeTokens;
75
98.3k
    maUnknownAttributes = rOther.maUnknownAttributes;
76
98.3k
}
77
78
css::uno::Reference< ::css::util::XCloneable > FastAttributeList::createClone()
79
7.81k
{
80
7.81k
    return new FastAttributeList(this);
81
7.81k
}
82
83
FastAttributeList::~FastAttributeList()
84
387k
{
85
387k
    free( mpChunk );
86
387k
}
87
88
void FastAttributeList::clear()
89
55.1M
{
90
55.1M
    maAttributeTokens.clear();
91
55.1M
    maAttributeValues.resize(1);
92
55.1M
    assert(maAttributeValues[0] == 0);
93
55.1M
    maUnknownAttributes.clear();
94
55.1M
}
95
96
void FastAttributeList::add( sal_Int32 nToken, std::string_view value )
97
18.7M
{
98
18.7M
    assert(nToken != -1);
99
18.7M
    assert(nToken != 0);
100
18.7M
    assert(value.length() < SAL_MAX_INT32); // protect against absurd values
101
18.7M
    maAttributeTokens.push_back( nToken );
102
18.7M
    sal_Int32 nWritePosition = maAttributeValues.back();
103
18.7M
    maAttributeValues.push_back( maAttributeValues.back() + value.length() + 1 );
104
18.7M
    if (maAttributeValues.back() > mnChunkLength)
105
102k
    {
106
102k
        const sal_Int32 newLen = std::max(mnChunkLength * 2, maAttributeValues.back());
107
102k
        auto p = static_cast<char*>(realloc(mpChunk, newLen));
108
102k
        if (!p)
109
0
            throw std::bad_alloc();
110
111
102k
        mnChunkLength = newLen;
112
102k
        mpChunk = p;
113
114
102k
    }
115
18.7M
    memcpy(mpChunk + nWritePosition, value.data(), value.length());
116
18.7M
    mpChunk[nWritePosition + value.length()] = '\0';
117
18.7M
}
118
119
void FastAttributeList::add(sal_Int32 nToken, std::u16string_view sValue)
120
0
{
121
0
    add(nToken, OUStringToOString(sValue, RTL_TEXTENCODING_UTF8));
122
0
}
123
124
void FastAttributeList::addNS( sal_Int32 nNamespaceToken, sal_Int32 nToken, std::string_view rValue )
125
0
{
126
0
    sal_Int32 nCombinedToken = (nNamespaceToken << 16) | nToken;
127
0
    add( nCombinedToken, rValue );
128
0
}
129
130
void FastAttributeList::addNS(sal_Int32 nNamespaceToken, sal_Int32 nToken,
131
                                     std::u16string_view sValue)
132
0
{
133
0
    sal_Int32 nCombinedToken = (nNamespaceToken << 16) | nToken;
134
0
    add(nCombinedToken, sValue);
135
0
}
136
137
void FastAttributeList::addUnknown( const OUString& rNamespaceURL, const OString& rName, const OString& value )
138
1.18M
{
139
1.18M
    maUnknownAttributes.emplace_back( rNamespaceURL, rName, value );
140
1.18M
}
141
142
void FastAttributeList::addUnknown( const OString& rName, const OString& value )
143
1.51M
{
144
1.51M
    maUnknownAttributes.emplace_back( rName, value );
145
1.51M
}
146
147
void FastAttributeList::add( const css::uno::Reference<css::xml::sax::XFastAttributeList>& xAttrList )
148
9.69k
{
149
9.69k
    const auto& rOther = castToFastAttributeList(xAttrList);
150
9.69k
    add(rOther);
151
9.69k
}
152
153
void FastAttributeList::add( const FastAttributeList& rOther )
154
9.69k
{
155
39.5k
    for (size_t i=0; i < rOther.maAttributeTokens.size(); ++i)
156
29.8k
        add(rOther.maAttributeTokens[i], rOther.getAsViewByIndex(i));
157
9.69k
    for (const auto & i : rOther.maUnknownAttributes)
158
31.1k
        addUnknown(i.maNamespaceURL, i.maName, i.maValue);
159
9.69k
}
160
161
// XFastAttributeList
162
sal_Bool FastAttributeList::hasAttribute( ::sal_Int32 Token )
163
10.6M
{
164
10.6M
    for (sal_Int32 i : maAttributeTokens)
165
18.8M
        if (i == Token)
166
1.90M
            return true;
167
168
8.69M
    return false;
169
10.6M
}
170
171
sal_Int32 FastAttributeList::getValueToken( ::sal_Int32 Token )
172
0
{
173
0
    for (size_t i = 0, n = maAttributeTokens.size(); i < n; ++i)
174
0
        if (maAttributeTokens[i] == Token)
175
0
            return getValueTokenByIndex(i);
176
177
0
    throw SAXException("FastAttributeList::getValueToken: unknown token " + OUString::number(Token), nullptr, Any());
178
0
}
179
180
sal_Int32 FastAttributeList::getOptionalValueToken( ::sal_Int32 Token, ::sal_Int32 Default )
181
11.7M
{
182
26.7M
    for (size_t i = 0, n = maAttributeTokens.size(); i < n; ++i)
183
17.2M
        if (maAttributeTokens[i] == Token)
184
2.18M
            return getValueTokenByIndex(i);
185
186
9.52M
    return Default;
187
11.7M
}
188
189
// performance sensitive shortcuts to avoid allocation ...
190
bool FastAttributeList::getAsInteger( sal_Int32 nToken, sal_Int32 &rInt) const
191
6.40M
{
192
6.40M
    rInt = 0;
193
16.2M
    for (size_t i = 0, n = maAttributeTokens.size(); i < n; ++i)
194
13.7M
        if (maAttributeTokens[i] == nToken)
195
3.95M
        {
196
3.95M
            rInt = getAsIntegerByIndex(i);
197
3.95M
            return true;
198
3.95M
        }
199
2.44M
    return false;
200
6.40M
}
201
202
bool FastAttributeList::getAsDouble( sal_Int32 nToken, double &rDouble) const
203
530k
{
204
530k
    rDouble = 0.0;
205
1.35M
    for (size_t i = 0, n = maAttributeTokens.size(); i < n; ++i)
206
1.14M
        if (maAttributeTokens[i] == nToken)
207
319k
        {
208
319k
            rDouble = o3tl::toDouble(getAsViewByIndex(i));
209
319k
            return true;
210
319k
        }
211
210k
    return false;
212
530k
}
213
214
bool FastAttributeList::getAsView( sal_Int32 nToken, std::string_view& rPos ) const
215
1.66M
{
216
1.85M
    for (size_t i = 0, n = maAttributeTokens.size(); i < n; ++i)
217
1.79M
    {
218
1.79M
        if (maAttributeTokens[i] != nToken)
219
188k
            continue;
220
221
1.60M
        rPos = getAsViewByIndex(i);
222
1.60M
        return true;
223
1.79M
    }
224
225
65.7k
    return false;
226
1.66M
}
227
228
OUString FastAttributeList::getValue( ::sal_Int32 Token )
229
33.3k
{
230
37.1k
    for (size_t i = 0, n = maAttributeTokens.size(); i < n; ++i)
231
35.9k
        if (maAttributeTokens[i] == Token)
232
32.1k
            return getValueByIndex(i);
233
234
1.21k
    throw SAXException("FastAttributeList::getValue: unknown token " + OUString::number(Token), nullptr, Any());
235
33.3k
}
236
237
OUString FastAttributeList::getOptionalValue( ::sal_Int32 Token )
238
4.09M
{
239
8.00M
    for (size_t i = 0, n = maAttributeTokens.size(); i < n; ++i)
240
6.77M
        if (maAttributeTokens[i] == Token)
241
2.86M
            return getValueByIndex(i);
242
243
1.22M
    return OUString();
244
4.09M
}
245
246
sal_Int32 FastAttributeList::getValueTokenByIndex(sal_Int32 nTokenIndex) const
247
2.82M
{
248
2.82M
    return FastTokenHandlerBase::getTokenFromChars(mpTokenHandler, getAsViewByIndex(nTokenIndex));
249
2.82M
}
250
251
Sequence< Attribute > FastAttributeList::getUnknownAttributes(  )
252
23.7M
{
253
23.7M
    auto nSize = maUnknownAttributes.size();
254
23.7M
    if (nSize == 0)
255
23.2M
        return {};
256
414k
    Sequence< Attribute > aSeq( nSize );
257
414k
    Attribute* pAttr = aSeq.getArray();
258
414k
    for( const auto& rAttr : maUnknownAttributes )
259
1.34M
        rAttr.FillAttribute( pAttr++ );
260
414k
    return aSeq;
261
23.7M
}
262
Sequence< FastAttribute > FastAttributeList::getFastAttributes(  )
263
20.2k
{
264
20.2k
    Sequence< FastAttribute > aSeq( maAttributeTokens.size() );
265
20.2k
    FastAttribute* pAttr = aSeq.getArray();
266
32.5k
    for (size_t i = 0, n = maAttributeTokens.size(); i < n; ++i)
267
12.3k
    {
268
12.3k
        pAttr->Token = maAttributeTokens[i];
269
12.3k
        pAttr->Value = getValueByIndex(i);
270
12.3k
        pAttr++;
271
12.3k
    }
272
20.2k
    return aSeq;
273
20.2k
}
274
275
FastAttributeList::FastAttributeIter FastAttributeList::find( sal_Int32 nToken ) const
276
2.89M
{
277
3.38M
    for (size_t i = 0, n = maAttributeTokens.size(); i < n; ++i)
278
512k
        if( maAttributeTokens[i] == nToken )
279
23.0k
            return FastAttributeIter(*this, i);
280
2.87M
    return end();
281
2.89M
}
282
283
sal_Int32 FastTokenHandlerBase::getTokenFromChars(
284
        const FastTokenHandlerBase *pTokenHandler,
285
        std::string_view token )
286
53.5M
{
287
53.5M
    return pTokenHandler->getTokenDirect(token);
288
53.5M
}
289
290
}
291
292
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */