Coverage Report

Created: 2025-12-08 09:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/sc/inc/recursionhelper.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 "formularesult.hxx"
23
24
#include <list>
25
#include <vector>
26
#include <stack>
27
#include <o3tl/sorted_vector.hxx>
28
29
class ScFormulaCell;
30
31
struct ScFormulaRecursionEntry
32
{
33
    ScFormulaCell*  pCell;
34
    bool            bOldRunning;
35
    ScFormulaResult aPreviousResult;
36
    ScFormulaRecursionEntry(
37
        ScFormulaCell* p, bool bR, const ScFormulaResult & rRes ) :
38
0
        pCell(p), bOldRunning(bR), aPreviousResult( rRes)
39
0
    {
40
0
    }
41
};
42
43
typedef ::std::list< ScFormulaRecursionEntry > ScFormulaRecursionList;
44
45
class ScRecursionHelper
46
{
47
    typedef ::std::stack< ScFormulaCell* >  ScRecursionInIterationStack;
48
    ScFormulaRecursionList              aRecursionFormulas;
49
    ScFormulaRecursionList::iterator    aInsertPos;
50
    ScFormulaRecursionList::iterator    aLastIterationStart;
51
    ScRecursionInIterationStack         aRecursionInIterationStack;
52
    std::vector< ScFormulaCell* >       aFGList;
53
    // Flag list corresponding to aFGList to indicate whether each formula-group
54
    // is in a dependency evaluation mode or not.
55
    std::vector< bool >                 aInDependencyEvalMode;
56
    sal_uInt16                              nRecursionCount;
57
    sal_uInt16                              nIteration;
58
    // Count of ScFormulaCell::CheckComputeDependencies in current call-stack.
59
    sal_uInt16                              nDependencyComputationLevel;
60
    bool                                bInRecursionReturn;
61
    bool                                bDoingRecursion;
62
    bool                                bInIterationReturn;
63
    bool                                bConverging;
64
    bool                                bGroupsIndependent;
65
    bool                                bAbortingDependencyComputation;
66
    std::vector< ScFormulaCell* >       aTemporaryGroupCells;
67
    o3tl::sorted_vector< ScFormulaCellGroup* >* pFGSet;
68
69
    void Init();
70
    void ResetIteration();
71
72
public:
73
74
    ScRecursionHelper();
75
624k
    sal_uInt16  GetRecursionCount() const       { return nRecursionCount; }
76
777k
    void    IncRecursionCount()             { ++nRecursionCount; }
77
777k
    void    DecRecursionCount()             { --nRecursionCount; }
78
23.5k
    sal_uInt16 GetDepComputeLevel() const   { return nDependencyComputationLevel; }
79
    void    IncDepComputeLevel();
80
    void    DecDepComputeLevel();
81
    /// A pure recursion return, no iteration.
82
0
    bool    IsInRecursionReturn() const     { return bInRecursionReturn &&
83
0
        !bInIterationReturn; }
84
    void SetInRecursionReturn( bool b );
85
0
    bool    IsDoingRecursion() const        { return bDoingRecursion; }
86
0
    void    SetDoingRecursion( bool b )     { bDoingRecursion = b; }
87
88
    void Insert( ScFormulaCell* p, bool bOldRunning, const ScFormulaResult & rRes );
89
90
0
    bool    IsInIterationReturn() const     { return bInIterationReturn; }
91
    void SetInIterationReturn( bool b );
92
777k
    bool    IsDoingIteration() const        { return nIteration > 0; }
93
624k
    sal_uInt16  GetIteration() const            { return nIteration; }
94
0
    bool &  GetConvergingReference()        { return bConverging; }
95
    void StartIteration();
96
    void ResumeIteration();
97
    void IncIteration();
98
    void EndIteration();
99
100
0
    const ScFormulaRecursionList::iterator& GetLastIterationStart() const { return aLastIterationStart; }
101
    ScFormulaRecursionList::iterator GetIterationStart();
102
    ScFormulaRecursionList::iterator GetIterationEnd();
103
    /** Any return, recursion or iteration, iteration is always coupled with
104
        recursion. */
105
1.80M
    bool    IsInReturn() const              { return bInRecursionReturn; }
106
0
    const ScFormulaRecursionList&   GetList() const { return aRecursionFormulas; }
107
0
    ScFormulaRecursionList&         GetList()       { return aRecursionFormulas; }
108
0
    ScRecursionInIterationStack&    GetRecursionInIterationStack()  { return aRecursionInIterationStack; }
109
110
    void Clear();
111
112
    /** Detects a simple cycle involving formula-groups and singleton formula-cells. */
113
    bool PushFormulaGroup(ScFormulaCell* pCell);
114
    void PopFormulaGroup();
115
    bool AnyCycleMemberInDependencyEvalMode(const ScFormulaCell* pCell);
116
    bool AnyParentFGInCycle();
117
    void SetFormulaGroupDepEvalMode(bool bSet);
118
    // When dependency computation detects a cycle, it may not compute proper cell values.
119
    // This sets a flag that ScFormulaCell will use to avoid setting those new values
120
    // and resetting the dirty flag, until the dependency computation bails out.
121
    void AbortDependencyComputation();
122
1.20M
    bool IsAbortingDependencyComputation() const { return bAbortingDependencyComputation; }
123
124
    void AddTemporaryGroupCell(ScFormulaCell* cell);
125
    void CleanTemporaryGroupCells();
126
127
0
    void SetFormulaGroupSet(o3tl::sorted_vector<ScFormulaCellGroup*>* pSet) { pFGSet = pSet; }
128
0
    bool HasFormulaGroupSet() const { return pFGSet != nullptr; }
129
    bool CheckFGIndependence(ScFormulaCellGroup* pFG);
130
0
    void SetGroupsIndependent(bool bSet) { bGroupsIndependent = bSet; }
131
1.29M
    bool AreGroupsIndependent() { return bGroupsIndependent; }
132
};
133
134
/** A class to wrap ScRecursionHelper::PushFormulaGroup(),
135
    ScRecursionHelper::PopFormulaGroup() and make these calls
136
    exception safe. */
137
class ScFormulaGroupCycleCheckGuard
138
{
139
    ScRecursionHelper& mrRecHelper;
140
    bool mbShouldPop;
141
public:
142
    ScFormulaGroupCycleCheckGuard() = delete;
143
    ScFormulaGroupCycleCheckGuard(ScRecursionHelper& rRecursionHelper, ScFormulaCell* pCell);
144
    ~ScFormulaGroupCycleCheckGuard();
145
146
};
147
148
class ScFormulaGroupDependencyComputeGuard
149
{
150
    ScRecursionHelper& mrRecHelper;
151
public:
152
    ScFormulaGroupDependencyComputeGuard() = delete;
153
    ScFormulaGroupDependencyComputeGuard(ScRecursionHelper& rRecursionHelper);
154
    ~ScFormulaGroupDependencyComputeGuard();
155
};
156
157
class ScCheckIndependentFGGuard
158
{
159
    ScRecursionHelper& mrRecHelper;
160
    bool mbUsedFGSet;
161
public:
162
    ScCheckIndependentFGGuard() = delete;
163
    ScCheckIndependentFGGuard(ScRecursionHelper& rRecursionHelper,
164
                              o3tl::sorted_vector<ScFormulaCellGroup*>* pSet);
165
    ~ScCheckIndependentFGGuard();
166
167
    bool AreGroupsIndependent();
168
};
169
170
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */