Coverage Report

Created: 2026-06-30 11:14

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/svl/source/items/IndexedStyleSheets.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
10
11
#include <svl/IndexedStyleSheets.hxx>
12
#include <svl/style.hxx>
13
14
#include <stdexcept>
15
#include <algorithm>
16
#include <utility>
17
18
19
namespace {
20
size_t family_to_index(SfxStyleFamily family)
21
17.7M
{
22
17.7M
    switch (family) {
23
0
    case SfxStyleFamily::Char:
24
0
        return 0;
25
786k
    case SfxStyleFamily::Para:
26
786k
        return 1;
27
65.0k
    case SfxStyleFamily::Frame:
28
65.0k
        return 2;
29
16.6M
    case SfxStyleFamily::Page:
30
16.6M
        return 3;
31
233k
    case SfxStyleFamily::Pseudo:
32
233k
        return 4;
33
0
    case SfxStyleFamily::Table:
34
0
        return 5;
35
0
    default: break;
36
17.7M
    }
37
17.7M
    assert(false); // only for compiler warning. all cases are handled in the switch
38
0
    return 0;
39
17.7M
}
40
}
41
42
namespace svl {
43
44
IndexedStyleSheets::IndexedStyleSheets()
45
287k
{
46
287k
}
47
48
void IndexedStyleSheets::Register(SfxStyleSheetBase& style, sal_Int32 pos)
49
2.12M
{
50
2.12M
    mPositionsByName.insert(std::make_pair(style.GetName(), pos));
51
2.12M
    size_t position = family_to_index(style.GetFamily());
52
2.12M
    mStyleSheetsByFamily.at(position).push_back(&style);
53
2.12M
}
54
55
void
56
IndexedStyleSheets::Reindex()
57
10.7k
{
58
10.7k
    mPositionsByName.clear();
59
75.2k
    for (size_t i = 0; i < NUMBER_OF_FAMILIES; i++) {
60
64.5k
        mStyleSheetsByFamily[i].clear();
61
64.5k
    }
62
63
10.7k
    sal_Int32 i = 0;
64
1.34M
    for (const auto& rxStyleSheet : mStyleSheets) {
65
1.34M
        SfxStyleSheetBase* p = rxStyleSheet.get();
66
1.34M
        Register(*p, i);
67
1.34M
        ++i;
68
1.34M
    }
69
10.7k
}
70
71
void
72
IndexedStyleSheets::ReindexOnNameChange(const SfxStyleSheetBase& style, const OUString& rOldName, const OUString& rNewName)
73
558
{
74
558
    std::pair<MapType::const_iterator, MapType::const_iterator> range = mPositionsByName.equal_range(rOldName);
75
558
    for (MapType::const_iterator it = range.first; it != range.second; ++it)
76
0
    {
77
0
        if (mStyleSheets[it->second].get() == &style)
78
0
        {
79
0
            unsigned nPos = it->second;
80
0
            mPositionsByName.erase(it);
81
0
            mPositionsByName.insert(std::make_pair(rNewName, nPos));
82
0
            break;
83
0
        }
84
0
    }
85
558
}
86
87
void
88
IndexedStyleSheets::AddStyleSheet(const rtl::Reference< SfxStyleSheetBase >& style)
89
784k
{
90
784k
    if (!HasStyleSheet(style)) {
91
784k
        mStyleSheets.push_back(style);
92
        // since we just added an element to the vector, we can safely do -1 as it will always be >= 1
93
784k
        Register(*style, mStyleSheets.size()-1);
94
784k
    }
95
784k
}
96
97
bool
98
IndexedStyleSheets::RemoveStyleSheet(const rtl::Reference< SfxStyleSheetBase >& style)
99
0
{
100
0
    std::pair<MapType::const_iterator, MapType::const_iterator> range = mPositionsByName.equal_range(style->GetName());
101
0
    for (MapType::const_iterator it = range.first; it != range.second; ++it)
102
0
    {
103
0
        sal_Int32 pos = it->second;
104
0
        if (mStyleSheets.at(pos) == style)
105
0
        {
106
0
            mStyleSheets.erase(mStyleSheets.begin() + pos);
107
0
            Reindex();
108
0
            return true;
109
0
        }
110
0
    }
111
0
    return false;
112
0
}
113
114
std::vector<sal_Int32> IndexedStyleSheets::FindPositionsByName(const OUString& name) const
115
0
{
116
0
    std::vector<sal_Int32> r;
117
0
    std::pair<MapType::const_iterator, MapType::const_iterator> range = mPositionsByName.equal_range(name);
118
0
    for (MapType::const_iterator it = range.first; it != range.second; ++it) {
119
0
        r.push_back(it->second);
120
0
    }
121
0
    return r;
122
0
}
123
124
std::vector<sal_Int32> IndexedStyleSheets::FindPositionsByNameAndPredicate(const OUString& name,
125
        StyleSheetPredicate& predicate, SearchBehavior behavior) const
126
9.23M
{
127
9.23M
    std::vector<sal_Int32> r;
128
9.23M
    auto range = mPositionsByName.equal_range(name);
129
9.88M
    for (auto it = range.first; it != range.second; ++it) {
130
5.89M
        sal_Int32 pos = it->second;
131
5.89M
        SfxStyleSheetBase *ssheet = mStyleSheets.at(pos).get();
132
5.89M
        if (predicate.Check(*ssheet)) {
133
5.24M
            r.push_back(pos);
134
5.24M
            if (behavior == SearchBehavior::ReturnFirst) {
135
5.24M
                break;
136
5.24M
            }
137
5.24M
        }
138
5.89M
    }
139
9.23M
    return r;
140
9.23M
}
141
142
143
sal_Int32
144
IndexedStyleSheets::GetNumberOfStyleSheetsWithPredicate(StyleSheetPredicate& predicate) const
145
0
{
146
0
    return std::count_if(mStyleSheets.begin(), mStyleSheets.end(),
147
0
        [&predicate](const rtl::Reference<SfxStyleSheetBase>& rxStyleSheet) {
148
0
            const SfxStyleSheetBase *ssheet = rxStyleSheet.get();
149
0
            return predicate.Check(*ssheet);
150
0
        });
151
0
}
152
153
std::pair<SfxStyleSheetBase*, sal_Int32>
154
IndexedStyleSheets::GetNthStyleSheetThatMatchesPredicate(
155
        sal_Int32 n,
156
        StyleSheetPredicate& predicate,
157
        sal_Int32 startAt)
158
0
{
159
0
    SfxStyleSheetBase* retval = nullptr;
160
0
    sal_Int32 matching = 0;
161
0
    VectorType::const_iterator it = mStyleSheets.begin()+startAt;
162
0
    for (; it != mStyleSheets.end(); ++it) {
163
0
        SfxStyleSheetBase *ssheet = it->get();
164
0
        if (predicate.Check(*ssheet)) {
165
0
            if (matching == n) {
166
0
                retval = it->get();
167
0
                break;
168
0
            }
169
0
            ++matching;
170
0
        }
171
0
    }
172
0
    return { retval, std::distance(mStyleSheets.cbegin(), it) };
173
0
}
174
175
sal_Int32 IndexedStyleSheets::FindStyleSheetPosition(const SfxStyleSheetBase& style) const
176
0
{
177
0
    VectorType::const_iterator it = std::find(mStyleSheets.begin(), mStyleSheets.end(), &style);
178
0
    if (it == mStyleSheets.end()) {
179
0
        throw std::runtime_error("IndexedStyleSheets::FindStylePosition Looked for style not in index");
180
0
    }
181
0
    return std::distance(mStyleSheets.begin(), it);
182
0
}
183
184
void
185
IndexedStyleSheets::Clear(StyleSheetDisposer& disposer)
186
302k
{
187
782k
    for (auto& rxStyleSheet : mStyleSheets) {
188
782k
        disposer.Dispose(rxStyleSheet);
189
190
        // tdf#161729 clear style sheets in same order as they were added
191
        // std::vector::clear() appears to delete elements in the
192
        // reverse order added. In the case of tdf#161729, a style
193
        // sheet's SfxItemSet can have a parent SfxItemSet and that
194
        // parent is the SfxItemSet for a style sheet added later.
195
        // Deleting from the end of the vector deletes a style sheet
196
        // and its SfxItemSet. If the now deleted SfxItemSet is a
197
        // parent SfxItemSet of a style sheet that was added earlier,
198
        // the style sheet added earlier will now have an SfxItemSet
199
        // with its parent set to an already deleted pointer. And so
200
        // a crash will occur when that earlier style sheet is deleted.
201
782k
        rxStyleSheet.clear();
202
782k
    }
203
302k
    mStyleSheets.clear();
204
302k
    mPositionsByName.clear();
205
302k
}
206
207
IndexedStyleSheets::~IndexedStyleSheets()
208
287k
{
209
287k
}
210
211
bool
212
IndexedStyleSheets::HasStyleSheet(const rtl::Reference< SfxStyleSheetBase >& style) const
213
784k
{
214
784k
    std::pair<MapType::const_iterator, MapType::const_iterator> range = mPositionsByName.equal_range(style->GetName());
215
862k
    for (MapType::const_iterator it = range.first; it != range.second; ++it)
216
77.3k
    {
217
77.3k
        if (mStyleSheets.at(it->second) == style)
218
0
            return true;
219
77.3k
    }
220
784k
    return false;
221
784k
}
222
223
SfxStyleSheetBase*
224
IndexedStyleSheets::GetStyleSheetByPosition(sal_Int32 pos)
225
5.24M
{
226
5.24M
    if( pos < static_cast<sal_Int32>(mStyleSheets.size()) )
227
5.24M
        return mStyleSheets.at(pos).get();
228
0
    return nullptr;
229
5.24M
}
230
231
void
232
IndexedStyleSheets::ApplyToAllStyleSheets(StyleSheetCallback& callback) const
233
0
{
234
0
    for (const auto& rxStyleSheet : mStyleSheets) {
235
0
        callback.DoIt(*rxStyleSheet);
236
0
    }
237
0
}
238
239
std::vector<sal_Int32>
240
IndexedStyleSheets::FindPositionsByPredicate(StyleSheetPredicate& predicate) const
241
0
{
242
0
    std::vector<sal_Int32> r;
243
0
    for (VectorType::const_iterator it = mStyleSheets.begin(); it != mStyleSheets.end(); ++it) {
244
0
        if (predicate.Check(**it)) {
245
0
            r.push_back(std::distance(mStyleSheets.begin(), it));
246
0
        }
247
0
    }
248
0
    return r;
249
0
}
250
251
const std::vector<SfxStyleSheetBase*>&
252
IndexedStyleSheets::GetStyleSheetsByFamily(SfxStyleFamily e) const
253
15.6M
{
254
15.6M
    size_t position = family_to_index(e);
255
15.6M
    return mStyleSheetsByFamily.at(position);
256
15.6M
}
257
258
} /* namespace svl */
259
260
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */