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