xref: /AOO41X/main/sc/inc/recursionhelper.hxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1*cdf0e10cSrcweir /*************************************************************************
2*cdf0e10cSrcweir  *
3*cdf0e10cSrcweir  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4*cdf0e10cSrcweir  *
5*cdf0e10cSrcweir  * Copyright 2000, 2010 Oracle and/or its affiliates.
6*cdf0e10cSrcweir  *
7*cdf0e10cSrcweir  * OpenOffice.org - a multi-platform office productivity suite
8*cdf0e10cSrcweir  *
9*cdf0e10cSrcweir  * This file is part of OpenOffice.org.
10*cdf0e10cSrcweir  *
11*cdf0e10cSrcweir  * OpenOffice.org is free software: you can redistribute it and/or modify
12*cdf0e10cSrcweir  * it under the terms of the GNU Lesser General Public License version 3
13*cdf0e10cSrcweir  * only, as published by the Free Software Foundation.
14*cdf0e10cSrcweir  *
15*cdf0e10cSrcweir  * OpenOffice.org is distributed in the hope that it will be useful,
16*cdf0e10cSrcweir  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17*cdf0e10cSrcweir  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18*cdf0e10cSrcweir  * GNU Lesser General Public License version 3 for more details
19*cdf0e10cSrcweir  * (a copy is included in the LICENSE file that accompanied this code).
20*cdf0e10cSrcweir  *
21*cdf0e10cSrcweir  * You should have received a copy of the GNU Lesser General Public License
22*cdf0e10cSrcweir  * version 3 along with OpenOffice.org.  If not, see
23*cdf0e10cSrcweir  * <http://www.openoffice.org/license.html>
24*cdf0e10cSrcweir  * for a copy of the LGPLv3 License.
25*cdf0e10cSrcweir  *
26*cdf0e10cSrcweir  ************************************************************************/
27*cdf0e10cSrcweir 
28*cdf0e10cSrcweir #ifndef INCLUDED_RECURSIONHELPER_HXX
29*cdf0e10cSrcweir #define INCLUDED_RECURSIONHELPER_HXX
30*cdf0e10cSrcweir 
31*cdf0e10cSrcweir #include "formularesult.hxx"
32*cdf0e10cSrcweir 
33*cdf0e10cSrcweir #include <list>
34*cdf0e10cSrcweir #include <stack>
35*cdf0e10cSrcweir #include <tools/solar.h>
36*cdf0e10cSrcweir 
37*cdf0e10cSrcweir class ScFormulaCell;
38*cdf0e10cSrcweir 
39*cdf0e10cSrcweir struct ScFormulaRecursionEntry
40*cdf0e10cSrcweir {
41*cdf0e10cSrcweir     ScFormulaCell*  pCell;
42*cdf0e10cSrcweir     sal_Bool            bOldRunning;
43*cdf0e10cSrcweir     ScFormulaResult aPreviousResult;
44*cdf0e10cSrcweir     ScFormulaRecursionEntry( ScFormulaCell* p, sal_Bool bR,
45*cdf0e10cSrcweir             const ScFormulaResult & rRes ) :
46*cdf0e10cSrcweir         pCell(p), bOldRunning(bR), aPreviousResult( rRes)
47*cdf0e10cSrcweir     {
48*cdf0e10cSrcweir     }
49*cdf0e10cSrcweir };
50*cdf0e10cSrcweir 
51*cdf0e10cSrcweir typedef ::std::list< ScFormulaRecursionEntry > ScFormulaRecursionList;
52*cdf0e10cSrcweir 
53*cdf0e10cSrcweir class ScRecursionHelper
54*cdf0e10cSrcweir {
55*cdf0e10cSrcweir     typedef ::std::stack< ScFormulaCell* >  ScRecursionInIterationStack;
56*cdf0e10cSrcweir     ScFormulaRecursionList              aRecursionFormulas;
57*cdf0e10cSrcweir     ScFormulaRecursionList::iterator    aInsertPos;
58*cdf0e10cSrcweir     ScFormulaRecursionList::iterator    aLastIterationStart;
59*cdf0e10cSrcweir     ScRecursionInIterationStack         aRecursionInIterationStack;
60*cdf0e10cSrcweir     sal_uInt16                              nRecursionCount;
61*cdf0e10cSrcweir     sal_uInt16                              nIteration;
62*cdf0e10cSrcweir     bool                                bInRecursionReturn;
63*cdf0e10cSrcweir     bool                                bDoingRecursion;
64*cdf0e10cSrcweir     bool                                bInIterationReturn;
65*cdf0e10cSrcweir     bool                                bConverging;
66*cdf0e10cSrcweir 
67*cdf0e10cSrcweir     void    Init()
68*cdf0e10cSrcweir     {
69*cdf0e10cSrcweir         nRecursionCount    = 0;
70*cdf0e10cSrcweir         bInRecursionReturn = bDoingRecursion = bInIterationReturn = false;
71*cdf0e10cSrcweir         aInsertPos = GetEnd();
72*cdf0e10cSrcweir         ResetIteration();
73*cdf0e10cSrcweir     }
74*cdf0e10cSrcweir     void    ResetIteration()
75*cdf0e10cSrcweir     {
76*cdf0e10cSrcweir         aLastIterationStart = GetEnd();
77*cdf0e10cSrcweir         nIteration = 0;
78*cdf0e10cSrcweir         bConverging = false;
79*cdf0e10cSrcweir     }
80*cdf0e10cSrcweir 
81*cdf0e10cSrcweir     public:
82*cdf0e10cSrcweir 
83*cdf0e10cSrcweir     ScRecursionHelper() { Init(); }
84*cdf0e10cSrcweir     sal_uInt16  GetRecursionCount() const       { return nRecursionCount; }
85*cdf0e10cSrcweir     void    IncRecursionCount()             { ++nRecursionCount; }
86*cdf0e10cSrcweir     void    DecRecursionCount()             { --nRecursionCount; }
87*cdf0e10cSrcweir     /// A pure recursion return, no iteration.
88*cdf0e10cSrcweir     bool    IsInRecursionReturn() const     { return bInRecursionReturn &&
89*cdf0e10cSrcweir         !bInIterationReturn; }
90*cdf0e10cSrcweir     void    SetInRecursionReturn( bool b )
91*cdf0e10cSrcweir     {
92*cdf0e10cSrcweir         // Do not use IsInRecursionReturn() here, it decouples iteration.
93*cdf0e10cSrcweir         if (b && !bInRecursionReturn)
94*cdf0e10cSrcweir             aInsertPos = aRecursionFormulas.begin();
95*cdf0e10cSrcweir         bInRecursionReturn = b;
96*cdf0e10cSrcweir     }
97*cdf0e10cSrcweir     bool    IsDoingRecursion() const        { return bDoingRecursion; }
98*cdf0e10cSrcweir     void    SetDoingRecursion( bool b )     { bDoingRecursion = b; }
99*cdf0e10cSrcweir     void    Insert( ScFormulaCell* p, sal_Bool bOldRunning,
100*cdf0e10cSrcweir                     const ScFormulaResult & rRes )
101*cdf0e10cSrcweir     {
102*cdf0e10cSrcweir         aRecursionFormulas.insert( aInsertPos, ScFormulaRecursionEntry( p,
103*cdf0e10cSrcweir                     bOldRunning, rRes));
104*cdf0e10cSrcweir     }
105*cdf0e10cSrcweir     ScFormulaRecursionList::iterator    GetStart()
106*cdf0e10cSrcweir     {
107*cdf0e10cSrcweir         return aRecursionFormulas.begin();
108*cdf0e10cSrcweir     }
109*cdf0e10cSrcweir     ScFormulaRecursionList::iterator    GetEnd()
110*cdf0e10cSrcweir     {
111*cdf0e10cSrcweir         return aRecursionFormulas.end();
112*cdf0e10cSrcweir     }
113*cdf0e10cSrcweir     bool    IsInIterationReturn() const     { return bInIterationReturn; }
114*cdf0e10cSrcweir     void    SetInIterationReturn( bool b )
115*cdf0e10cSrcweir     {
116*cdf0e10cSrcweir         // An iteration return is always coupled to a recursion return.
117*cdf0e10cSrcweir         SetInRecursionReturn( b);
118*cdf0e10cSrcweir         bInIterationReturn = b;
119*cdf0e10cSrcweir     }
120*cdf0e10cSrcweir     bool    IsDoingIteration() const        { return nIteration > 0; }
121*cdf0e10cSrcweir     sal_uInt16  GetIteration() const            { return nIteration; }
122*cdf0e10cSrcweir     bool &  GetConvergingReference()        { return bConverging; }
123*cdf0e10cSrcweir     void    StartIteration()
124*cdf0e10cSrcweir     {
125*cdf0e10cSrcweir         SetInIterationReturn( false);
126*cdf0e10cSrcweir         nIteration = 1;
127*cdf0e10cSrcweir         bConverging = false;
128*cdf0e10cSrcweir         aLastIterationStart = GetIterationStart();
129*cdf0e10cSrcweir     }
130*cdf0e10cSrcweir     void    ResumeIteration()
131*cdf0e10cSrcweir     {
132*cdf0e10cSrcweir         SetInIterationReturn( false);
133*cdf0e10cSrcweir         aLastIterationStart = GetIterationStart();
134*cdf0e10cSrcweir     }
135*cdf0e10cSrcweir     void    IncIteration()                  { ++nIteration; }
136*cdf0e10cSrcweir     void    EndIteration()
137*cdf0e10cSrcweir     {
138*cdf0e10cSrcweir         aRecursionFormulas.erase( GetIterationStart(), GetIterationEnd());
139*cdf0e10cSrcweir         ResetIteration();
140*cdf0e10cSrcweir     }
141*cdf0e10cSrcweir     ScFormulaRecursionList::iterator GetLastIterationStart() { return aLastIterationStart; }
142*cdf0e10cSrcweir     ScFormulaRecursionList::iterator GetIterationStart() { return GetStart(); }
143*cdf0e10cSrcweir     ScFormulaRecursionList::iterator GetIterationEnd() { return GetEnd(); }
144*cdf0e10cSrcweir     /** Any return, recursion or iteration, iteration is always coupled with
145*cdf0e10cSrcweir         recursion. */
146*cdf0e10cSrcweir     bool    IsInReturn() const              { return bInRecursionReturn; }
147*cdf0e10cSrcweir     const ScFormulaRecursionList&   GetList() const { return aRecursionFormulas; }
148*cdf0e10cSrcweir     ScFormulaRecursionList&         GetList()       { return aRecursionFormulas; }
149*cdf0e10cSrcweir     ScRecursionInIterationStack&    GetRecursionInIterationStack()  { return aRecursionInIterationStack; }
150*cdf0e10cSrcweir     void    Clear()
151*cdf0e10cSrcweir     {
152*cdf0e10cSrcweir         aRecursionFormulas.clear();
153*cdf0e10cSrcweir         while (!aRecursionInIterationStack.empty())
154*cdf0e10cSrcweir             aRecursionInIterationStack.pop();
155*cdf0e10cSrcweir         Init();
156*cdf0e10cSrcweir     }
157*cdf0e10cSrcweir };
158*cdf0e10cSrcweir 
159*cdf0e10cSrcweir #endif // INCLUDED_RECURSIONHELPER_HXX
160