Coverage Report

Created: 2026-02-14 09:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/sc/inc/compressedarray.hxx
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
#pragma once
21
22
#include <cstddef>
23
#include <memory>
24
25
#include "scdllapi.h"
26
27
/** Compressed array of row (or column) entries, e.g. heights, flags, ...
28
29
    The array stores ranges of values such that equal consecutive values occupy only
30
    one entry. Initially it consists of one DataEntry with an implied start
31
    row/column of 0 and an end row/column of access type maximum value.
32
33
    typename A := access type, e.g. SCROW or SCCOL, must be a POD.
34
35
    typename D := data type, e.g. sal_uInt16 or sal_uInt8 or whatever, may also be a
36
    struct or class.
37
38
    D::operator==() and D::operator=() must be implemented. Force template
39
    instantiation for a specific type in source/core/data/compressedarray.cxx
40
41
    TODO: Currently the allocated memory never shrinks, must manually invoke
42
    Resize() if needed.
43
 */
44
45
template< typename A, typename D > class ScCompressedArray
46
{
47
public:
48
    class Iterator
49
    {
50
        friend ScCompressedArray;
51
        const ScCompressedArray& mrArray;
52
        size_t             mnIndex = 0;
53
        A                  mnRegion = 0;
54
112k
        Iterator(const ScCompressedArray& rArray) : mrArray(rArray) {}
ScCompressedArray<short, unsigned short>::Iterator::Iterator(ScCompressedArray<short, unsigned short> const&)
Line
Count
Source
54
112k
        Iterator(const ScCompressedArray& rArray) : mrArray(rArray) {}
Unexecuted instantiation: ScCompressedArray<int, CRFlags>::Iterator::Iterator(ScCompressedArray<int, CRFlags> const&)
Unexecuted instantiation: ScCompressedArray<short, CRFlags>::Iterator::Iterator(ScCompressedArray<short, CRFlags> const&)
Unexecuted instantiation: ScCompressedArray<int, unsigned short>::Iterator::Iterator(ScCompressedArray<int, unsigned short> const&)
55
28
        Iterator(const ScCompressedArray& rArray, size_t nIndex, A nRegion) : mrArray(rArray), mnIndex(nIndex), mnRegion(nRegion) {}
Unexecuted instantiation: ScCompressedArray<int, CRFlags>::Iterator::Iterator(ScCompressedArray<int, CRFlags> const&, unsigned long, int)
ScCompressedArray<short, unsigned short>::Iterator::Iterator(ScCompressedArray<short, unsigned short> const&, unsigned long, short)
Line
Count
Source
55
28
        Iterator(const ScCompressedArray& rArray, size_t nIndex, A nRegion) : mrArray(rArray), mnIndex(nIndex), mnRegion(nRegion) {}
Unexecuted instantiation: ScCompressedArray<short, CRFlags>::Iterator::Iterator(ScCompressedArray<short, CRFlags> const&, unsigned long, short)
Unexecuted instantiation: ScCompressedArray<int, unsigned short>::Iterator::Iterator(ScCompressedArray<int, unsigned short> const&, unsigned long, int)
56
    public:
57
        void operator++();
58
        Iterator operator+(size_t) const;
59
570M
        const D & operator*() const { return mrArray.pData[mnIndex].aValue; }
ScCompressedArray<short, unsigned short>::Iterator::operator*() const
Line
Count
Source
59
570M
        const D & operator*() const { return mrArray.pData[mnIndex].aValue; }
Unexecuted instantiation: ScCompressedArray<int, CRFlags>::Iterator::operator*() const
Unexecuted instantiation: ScCompressedArray<short, CRFlags>::Iterator::operator*() const
Unexecuted instantiation: ScCompressedArray<int, unsigned short>::Iterator::operator*() const
60
    };
61
    struct DataEntry
62
    {
63
        A   nEnd;           // start is end of previous entry + 1
64
        D   aValue;
65
    };
66
    struct RangeData
67
    {
68
        A mnRow1, mnRow2;
69
        D maValue;
70
    };
71
72
    /** Construct with nMaxAccess=MAXROW, for example. */
73
                                ScCompressedArray( A nMaxAccess,
74
                                        const D& rValue );
75
    void                        Reset( const D& rValue );
76
    void                        SetValue( A nPos, const D& rValue );
77
    void                        SetValue( A nStart, A nEnd, const D& rValue );
78
    [[nodiscard]]
79
    const D&                    GetValue( A nPos ) const;
80
    [[nodiscard]]
81
0
    A                           GetLastPos() const { return pData[nCount-1].nEnd; }
Unexecuted instantiation: ScCompressedArray<short, unsigned short>::GetLastPos() const
Unexecuted instantiation: ScCompressedArray<int, CRFlags>::GetLastPos() const
Unexecuted instantiation: ScCompressedArray<short, CRFlags>::GetLastPos() const
Unexecuted instantiation: ScCompressedArray<int, unsigned short>::GetLastPos() const
82
83
    /** Get value for a row, and it's region end row */
84
    [[nodiscard]]
85
    const D&                    GetValue( A nPos, size_t& nIndex, A& nEnd ) const;
86
87
    /** Get range data for a row, i.e. value and start and end rows with that value */
88
    [[nodiscard]]
89
    RangeData                   GetRangeData( A nPos ) const;
90
91
    /** Get next value and it's region end row. If nIndex<nCount, nIndex is
92
        incremented first. If the resulting nIndex>=nCount, the value of the
93
        last entry is returned again. */
94
    [[nodiscard]]
95
    const D&                    GetNextValue( size_t& nIndex, A& nEnd ) const;
96
97
    /** Insert rows before nStart and copy value for inserted rows from
98
        nStart-1, return that value. */
99
    const D&                    Insert( A nStart, size_t nCount );
100
    void                        InsertPreservingSize( A nStart, size_t nCount, const D& rFillValue );
101
102
    void                        Remove( A nStart, size_t nCount );
103
    void                        RemovePreservingSize( A nStart, size_t nCount, const D& rFillValue );
104
105
    /** Copy rArray.nStart+nSourceDy to this.nStart */
106
    void                        CopyFrom( const ScCompressedArray& rArray,
107
                                    A nStart, A nEnd )
108
42
                                { CopyFrom(rArray, nStart, nEnd, nStart); }
ScCompressedArray<short, unsigned short>::CopyFrom(ScCompressedArray<short, unsigned short> const&, short, short)
Line
Count
Source
108
14
                                { CopyFrom(rArray, nStart, nEnd, nStart); }
ScCompressedArray<short, CRFlags>::CopyFrom(ScCompressedArray<short, CRFlags> const&, short, short)
Line
Count
Source
108
14
                                { CopyFrom(rArray, nStart, nEnd, nStart); }
ScCompressedArray<int, CRFlags>::CopyFrom(ScCompressedArray<int, CRFlags> const&, int, int)
Line
Count
Source
108
14
                                { CopyFrom(rArray, nStart, nEnd, nStart); }
Unexecuted instantiation: ScCompressedArray<int, unsigned short>::CopyFrom(ScCompressedArray<int, unsigned short> const&, int, int)
109
    void                        CopyFrom( const ScCompressedArray& rArray,
110
                                    A nDestStart, A nDestEnd, A nSrcStart );
111
112
    // methods public for the coupled array sum methods
113
    /** Obtain index into entries for nPos */
114
    SC_DLLPUBLIC size_t                      Search( A nPos ) const;
115
116
112k
    Iterator                    begin() const { return Iterator(*this); }
ScCompressedArray<short, unsigned short>::begin() const
Line
Count
Source
116
112k
    Iterator                    begin() const { return Iterator(*this); }
Unexecuted instantiation: ScCompressedArray<int, CRFlags>::begin() const
Unexecuted instantiation: ScCompressedArray<short, CRFlags>::begin() const
Unexecuted instantiation: ScCompressedArray<int, unsigned short>::begin() const
117
118
protected:
119
    size_t                      nCount;
120
    size_t                      nLimit;
121
    std::unique_ptr<DataEntry[]> pData;
122
    A                           nMaxAccess;
123
};
124
125
template< typename A, typename D >
126
void ScCompressedArray<A,D>::Reset( const D& rValue )
127
1.15k
{
128
    // Create a temporary copy in case we got a reference passed that points to
129
    // a part of the array to be reallocated.
130
1.15k
    D aTmpVal( rValue);
131
1.15k
    nCount = nLimit = 1;
132
1.15k
    pData.reset(new DataEntry[1]);
133
1.15k
    pData[0].aValue = aTmpVal;
134
1.15k
    pData[0].nEnd = nMaxAccess;
135
1.15k
}
ScCompressedArray<int, CRFlags>::Reset(CRFlags const&)
Line
Count
Source
127
337
{
128
    // Create a temporary copy in case we got a reference passed that points to
129
    // a part of the array to be reallocated.
130
337
    D aTmpVal( rValue);
131
337
    nCount = nLimit = 1;
132
337
    pData.reset(new DataEntry[1]);
133
337
    pData[0].aValue = aTmpVal;
134
337
    pData[0].nEnd = nMaxAccess;
135
337
}
Unexecuted instantiation: ScCompressedArray<short, unsigned short>::Reset(unsigned short const&)
Unexecuted instantiation: ScCompressedArray<short, CRFlags>::Reset(CRFlags const&)
ScCompressedArray<int, unsigned short>::Reset(unsigned short const&)
Line
Count
Source
127
813
{
128
    // Create a temporary copy in case we got a reference passed that points to
129
    // a part of the array to be reallocated.
130
813
    D aTmpVal( rValue);
131
813
    nCount = nLimit = 1;
132
813
    pData.reset(new DataEntry[1]);
133
813
    pData[0].aValue = aTmpVal;
134
813
    pData[0].nEnd = nMaxAccess;
135
813
}
136
137
template< typename A, typename D >
138
void ScCompressedArray<A,D>::SetValue( A nPos, const D& rValue )
139
130M
{
140
130M
    SetValue( nPos, nPos, rValue);
141
130M
}
ScCompressedArray<short, unsigned short>::SetValue(short, unsigned short const&)
Line
Count
Source
139
130M
{
140
130M
    SetValue( nPos, nPos, rValue);
141
130M
}
ScCompressedArray<int, CRFlags>::SetValue(int, CRFlags const&)
Line
Count
Source
139
30.7k
{
140
30.7k
    SetValue( nPos, nPos, rValue);
141
30.7k
}
Unexecuted instantiation: ScCompressedArray<short, CRFlags>::SetValue(short, CRFlags const&)
Unexecuted instantiation: ScCompressedArray<int, unsigned short>::SetValue(int, unsigned short const&)
142
143
template< typename A, typename D >
144
const D& ScCompressedArray<A,D>::GetValue( A nPos ) const
145
522M
{
146
522M
    size_t nIndex = Search( nPos);
147
522M
    return pData[nIndex].aValue;
148
522M
}
ScCompressedArray<int, unsigned short>::GetValue(int) const
Line
Count
Source
145
164k
{
146
164k
    size_t nIndex = Search( nPos);
147
164k
    return pData[nIndex].aValue;
148
164k
}
ScCompressedArray<short, unsigned short>::GetValue(short) const
Line
Count
Source
145
522M
{
146
522M
    size_t nIndex = Search( nPos);
147
522M
    return pData[nIndex].aValue;
148
522M
}
ScCompressedArray<int, CRFlags>::GetValue(int) const
Line
Count
Source
145
144k
{
146
144k
    size_t nIndex = Search( nPos);
147
144k
    return pData[nIndex].aValue;
148
144k
}
Unexecuted instantiation: ScCompressedArray<short, CRFlags>::GetValue(short) const
149
150
template< typename A, typename D >
151
const D& ScCompressedArray<A,D>::GetValue( A nPos, size_t& nIndex, A& nEnd ) const
152
1.82M
{
153
1.82M
    nIndex = Search( nPos);
154
1.82M
    nEnd = pData[nIndex].nEnd;
155
1.82M
    return pData[nIndex].aValue;
156
1.82M
}
ScCompressedArray<int, CRFlags>::GetValue(int, unsigned long&, int&) const
Line
Count
Source
152
30.3k
{
153
30.3k
    nIndex = Search( nPos);
154
30.3k
    nEnd = pData[nIndex].nEnd;
155
30.3k
    return pData[nIndex].aValue;
156
30.3k
}
ScCompressedArray<int, unsigned short>::GetValue(int, unsigned long&, int&) const
Line
Count
Source
152
1.79M
{
153
1.79M
    nIndex = Search( nPos);
154
1.79M
    nEnd = pData[nIndex].nEnd;
155
1.79M
    return pData[nIndex].aValue;
156
1.79M
}
ScCompressedArray<short, unsigned short>::GetValue(short, unsigned long&, short&) const
Line
Count
Source
152
14
{
153
14
    nIndex = Search( nPos);
154
14
    nEnd = pData[nIndex].nEnd;
155
14
    return pData[nIndex].aValue;
156
14
}
ScCompressedArray<short, CRFlags>::GetValue(short, unsigned long&, short&) const
Line
Count
Source
152
14
{
153
14
    nIndex = Search( nPos);
154
14
    nEnd = pData[nIndex].nEnd;
155
14
    return pData[nIndex].aValue;
156
14
}
157
158
template< typename A, typename D >
159
typename ScCompressedArray<A,D>::RangeData ScCompressedArray<A,D>::GetRangeData( A nPos ) const
160
15.8k
{
161
15.8k
    size_t nIndex = Search( nPos);
162
15.8k
    RangeData aData;
163
15.8k
    aData.mnRow1 = nIndex == 0 ? 0 : pData[nIndex - 1].nEnd + 1;
164
15.8k
    aData.mnRow2 = pData[nIndex].nEnd;
165
15.8k
    aData.maValue = pData[nIndex].aValue;
166
15.8k
    return aData;
167
15.8k
}
ScCompressedArray<int, unsigned short>::GetRangeData(int) const
Line
Count
Source
160
15.8k
{
161
15.8k
    size_t nIndex = Search( nPos);
162
15.8k
    RangeData aData;
163
15.8k
    aData.mnRow1 = nIndex == 0 ? 0 : pData[nIndex - 1].nEnd + 1;
164
15.8k
    aData.mnRow2 = pData[nIndex].nEnd;
165
15.8k
    aData.maValue = pData[nIndex].aValue;
166
15.8k
    return aData;
167
15.8k
}
Unexecuted instantiation: ScCompressedArray<int, CRFlags>::GetRangeData(int) const
Unexecuted instantiation: ScCompressedArray<short, unsigned short>::GetRangeData(short) const
Unexecuted instantiation: ScCompressedArray<short, CRFlags>::GetRangeData(short) const
168
169
template< typename A, typename D >
170
const D& ScCompressedArray<A,D>::GetNextValue( size_t& nIndex, A& nEnd ) const
171
270
{
172
270
    if (nIndex < nCount)
173
270
        ++nIndex;
174
270
    size_t nEntry = (nIndex < nCount ? nIndex : nCount-1);
175
270
    nEnd = pData[nEntry].nEnd;
176
270
    return pData[nEntry].aValue;
177
270
}
ScCompressedArray<int, CRFlags>::GetNextValue(unsigned long&, int&) const
Line
Count
Source
171
228
{
172
228
    if (nIndex < nCount)
173
228
        ++nIndex;
174
228
    size_t nEntry = (nIndex < nCount ? nIndex : nCount-1);
175
228
    nEnd = pData[nEntry].nEnd;
176
228
    return pData[nEntry].aValue;
177
228
}
ScCompressedArray<short, unsigned short>::GetNextValue(unsigned long&, short&) const
Line
Count
Source
171
42
{
172
42
    if (nIndex < nCount)
173
42
        ++nIndex;
174
42
    size_t nEntry = (nIndex < nCount ? nIndex : nCount-1);
175
42
    nEnd = pData[nEntry].nEnd;
176
42
    return pData[nEntry].aValue;
177
42
}
Unexecuted instantiation: ScCompressedArray<short, CRFlags>::GetNextValue(unsigned long&, short&) const
Unexecuted instantiation: ScCompressedArray<int, unsigned short>::GetNextValue(unsigned long&, int&) const
178
179
//  ScBitMaskCompressedArray
180
/** The data type represents bits, manageable by bitwise operations.
181
 */
182
183
template< typename A, typename D > class ScBitMaskCompressedArray final : public ScCompressedArray<A,D>
184
{
185
public:
186
                                ScBitMaskCompressedArray( A nMaxAccessP,
187
                                        const D& rValue )
188
491k
                                    : ScCompressedArray<A,D>( nMaxAccessP, rValue )
189
491k
                                    {}
ScBitMaskCompressedArray<short, CRFlags>::ScBitMaskCompressedArray(short, CRFlags const&)
Line
Count
Source
188
245k
                                    : ScCompressedArray<A,D>( nMaxAccessP, rValue )
189
245k
                                    {}
ScBitMaskCompressedArray<int, CRFlags>::ScBitMaskCompressedArray(int, CRFlags const&)
Line
Count
Source
188
245k
                                    : ScCompressedArray<A,D>( nMaxAccessP, rValue )
189
245k
                                    {}
190
    void                        AndValue( A nPos, const D& rValueToAnd );
191
    void                        OrValue( A nPos, const D& rValueToOr );
192
    void                        AndValue( A nStart, A nEnd, const D& rValueToAnd );
193
    void                        OrValue( A nStart, A nEnd, const D& rValueToOr );
194
195
    /** Copy values from rArray and bitwise AND them with rValueToAnd. */
196
    void                        CopyFromAnded(
197
                                    const ScBitMaskCompressedArray& rArray,
198
                                    A nStart, A nEnd, const D& rValueToAnd );
199
200
    /** Return the last row where an entry meets the condition:
201
        ((aValue & rBitMask) != 0), start searching at 0. If no entry
202
        meets this condition, ::std::numeric_limits<A>::max() is returned. */
203
    A                           GetLastAnyBitAccess( const D& rBitMask ) const;
204
};
205
206
template< typename A, typename D >
207
void ScBitMaskCompressedArray<A,D>::AndValue( A nPos, const D& rValueToAnd )
208
0
{
209
0
    const D& rValue = this->GetValue( nPos);
210
0
    if ((rValue & rValueToAnd) != rValue)
211
0
        this->SetValue( nPos, rValue & rValueToAnd);
212
0
}
Unexecuted instantiation: ScBitMaskCompressedArray<int, CRFlags>::AndValue(int, CRFlags const&)
Unexecuted instantiation: ScBitMaskCompressedArray<short, CRFlags>::AndValue(short, CRFlags const&)
213
214
template< typename A, typename D >
215
void ScBitMaskCompressedArray<A,D>::OrValue( A nPos, const D& rValueToOr )
216
0
{
217
0
    const D& rValue = this->GetValue( nPos);
218
0
    if ((rValue | rValueToOr) != rValue)
219
0
        this->SetValue( nPos, rValue | rValueToOr);
220
0
}
Unexecuted instantiation: ScBitMaskCompressedArray<int, CRFlags>::OrValue(int, CRFlags const&)
Unexecuted instantiation: ScBitMaskCompressedArray<short, CRFlags>::OrValue(short, CRFlags const&)
221
222
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */