1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 #ifndef INCLUDED_RECURSIONHELPER_HXX 25 #define INCLUDED_RECURSIONHELPER_HXX 26 27 #include "formularesult.hxx" 28 29 #include <list> 30 #include <stack> 31 #include <tools/solar.h> 32 33 class ScFormulaCell; 34 35 struct ScFormulaRecursionEntry 36 { 37 ScFormulaCell* pCell; 38 sal_Bool bOldRunning; 39 ScFormulaResult aPreviousResult; ScFormulaRecursionEntryScFormulaRecursionEntry40 ScFormulaRecursionEntry( ScFormulaCell* p, sal_Bool bR, 41 const ScFormulaResult & rRes ) : 42 pCell(p), bOldRunning(bR), aPreviousResult( rRes) 43 { 44 } 45 }; 46 47 typedef ::std::list< ScFormulaRecursionEntry > ScFormulaRecursionList; 48 49 class ScRecursionHelper 50 { 51 typedef ::std::stack< ScFormulaCell* > ScRecursionInIterationStack; 52 ScFormulaRecursionList aRecursionFormulas; 53 ScFormulaRecursionList::iterator aInsertPos; 54 ScFormulaRecursionList::iterator aLastIterationStart; 55 ScRecursionInIterationStack aRecursionInIterationStack; 56 sal_uInt16 nRecursionCount; 57 sal_uInt16 nIteration; 58 bool bInRecursionReturn; 59 bool bDoingRecursion; 60 bool bInIterationReturn; 61 bool bConverging; 62 Init()63 void Init() 64 { 65 nRecursionCount = 0; 66 bInRecursionReturn = bDoingRecursion = bInIterationReturn = false; 67 aInsertPos = GetEnd(); 68 ResetIteration(); 69 } ResetIteration()70 void ResetIteration() 71 { 72 aLastIterationStart = GetEnd(); 73 nIteration = 0; 74 bConverging = false; 75 } 76 77 public: 78 ScRecursionHelper()79 ScRecursionHelper() { Init(); } GetRecursionCount() const80 sal_uInt16 GetRecursionCount() const { return nRecursionCount; } IncRecursionCount()81 void IncRecursionCount() { ++nRecursionCount; } DecRecursionCount()82 void DecRecursionCount() { --nRecursionCount; } 83 /// A pure recursion return, no iteration. IsInRecursionReturn() const84 bool IsInRecursionReturn() const { return bInRecursionReturn && 85 !bInIterationReturn; } SetInRecursionReturn(bool b)86 void SetInRecursionReturn( bool b ) 87 { 88 // Do not use IsInRecursionReturn() here, it decouples iteration. 89 if (b && !bInRecursionReturn) 90 aInsertPos = aRecursionFormulas.begin(); 91 bInRecursionReturn = b; 92 } IsDoingRecursion() const93 bool IsDoingRecursion() const { return bDoingRecursion; } SetDoingRecursion(bool b)94 void SetDoingRecursion( bool b ) { bDoingRecursion = b; } Insert(ScFormulaCell * p,sal_Bool bOldRunning,const ScFormulaResult & rRes)95 void Insert( ScFormulaCell* p, sal_Bool bOldRunning, 96 const ScFormulaResult & rRes ) 97 { 98 aRecursionFormulas.insert( aInsertPos, ScFormulaRecursionEntry( p, 99 bOldRunning, rRes)); 100 } GetStart()101 ScFormulaRecursionList::iterator GetStart() 102 { 103 return aRecursionFormulas.begin(); 104 } GetEnd()105 ScFormulaRecursionList::iterator GetEnd() 106 { 107 return aRecursionFormulas.end(); 108 } IsInIterationReturn() const109 bool IsInIterationReturn() const { return bInIterationReturn; } SetInIterationReturn(bool b)110 void SetInIterationReturn( bool b ) 111 { 112 // An iteration return is always coupled to a recursion return. 113 SetInRecursionReturn( b); 114 bInIterationReturn = b; 115 } IsDoingIteration() const116 bool IsDoingIteration() const { return nIteration > 0; } GetIteration() const117 sal_uInt16 GetIteration() const { return nIteration; } GetConvergingReference()118 bool & GetConvergingReference() { return bConverging; } StartIteration()119 void StartIteration() 120 { 121 SetInIterationReturn( false); 122 nIteration = 1; 123 bConverging = false; 124 aLastIterationStart = GetIterationStart(); 125 } ResumeIteration()126 void ResumeIteration() 127 { 128 SetInIterationReturn( false); 129 aLastIterationStart = GetIterationStart(); 130 } IncIteration()131 void IncIteration() { ++nIteration; } EndIteration()132 void EndIteration() 133 { 134 aRecursionFormulas.erase( GetIterationStart(), GetIterationEnd()); 135 ResetIteration(); 136 } GetLastIterationStart()137 ScFormulaRecursionList::iterator GetLastIterationStart() { return aLastIterationStart; } GetIterationStart()138 ScFormulaRecursionList::iterator GetIterationStart() { return GetStart(); } GetIterationEnd()139 ScFormulaRecursionList::iterator GetIterationEnd() { return GetEnd(); } 140 /** Any return, recursion or iteration, iteration is always coupled with 141 recursion. */ IsInReturn() const142 bool IsInReturn() const { return bInRecursionReturn; } GetList() const143 const ScFormulaRecursionList& GetList() const { return aRecursionFormulas; } GetList()144 ScFormulaRecursionList& GetList() { return aRecursionFormulas; } GetRecursionInIterationStack()145 ScRecursionInIterationStack& GetRecursionInIterationStack() { return aRecursionInIterationStack; } Clear()146 void Clear() 147 { 148 aRecursionFormulas.clear(); 149 while (!aRecursionInIterationStack.empty()) 150 aRecursionInIterationStack.pop(); 151 Init(); 152 } 153 }; 154 155 #endif // INCLUDED_RECURSIONHELPER_HXX 156