summaryrefslogtreecommitdiffstats
path: root/sc/inc/recursionhelper.hxx
diff options
context:
space:
mode:
Diffstat (limited to 'sc/inc/recursionhelper.hxx')
-rw-r--r--sc/inc/recursionhelper.hxx170
1 files changed, 170 insertions, 0 deletions
diff --git a/sc/inc/recursionhelper.hxx b/sc/inc/recursionhelper.hxx
new file mode 100644
index 000000000..6c4850905
--- /dev/null
+++ b/sc/inc/recursionhelper.hxx
@@ -0,0 +1,170 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include "formularesult.hxx"
+
+#include <list>
+#include <vector>
+#include <stack>
+#include <o3tl/sorted_vector.hxx>
+
+class ScFormulaCell;
+
+struct ScFormulaRecursionEntry
+{
+ ScFormulaCell* pCell;
+ bool bOldRunning;
+ ScFormulaResult aPreviousResult;
+ ScFormulaRecursionEntry(
+ ScFormulaCell* p, bool bR, const ScFormulaResult & rRes ) :
+ pCell(p), bOldRunning(bR), aPreviousResult( rRes)
+ {
+ }
+};
+
+typedef ::std::list< ScFormulaRecursionEntry > ScFormulaRecursionList;
+
+class ScRecursionHelper
+{
+ typedef ::std::stack< ScFormulaCell* > ScRecursionInIterationStack;
+ ScFormulaRecursionList aRecursionFormulas;
+ ScFormulaRecursionList::iterator aInsertPos;
+ ScFormulaRecursionList::iterator aLastIterationStart;
+ ScRecursionInIterationStack aRecursionInIterationStack;
+ std::vector< ScFormulaCell* > aFGList;
+ // Flag list corresponding to aFGList to indicate whether each formula-group
+ // is in a dependency evaluation mode or not.
+ std::vector< bool > aInDependencyEvalMode;
+ sal_uInt16 nRecursionCount;
+ sal_uInt16 nIteration;
+ // Count of ScFormulaCell::CheckComputeDependencies in current call-stack.
+ sal_uInt16 nDependencyComputationLevel;
+ bool bInRecursionReturn;
+ bool bDoingRecursion;
+ bool bInIterationReturn;
+ bool bConverging;
+ bool bGroupsIndependent;
+ bool bAbortingDependencyComputation;
+ std::vector< ScFormulaCell* > aTemporaryGroupCells;
+ o3tl::sorted_vector< ScFormulaCellGroup* >* pFGSet;
+
+ void Init();
+ void ResetIteration();
+
+public:
+
+ ScRecursionHelper();
+ sal_uInt16 GetRecursionCount() const { return nRecursionCount; }
+ void IncRecursionCount() { ++nRecursionCount; }
+ void DecRecursionCount() { --nRecursionCount; }
+ sal_uInt16 GetDepComputeLevel() const { return nDependencyComputationLevel; }
+ void IncDepComputeLevel();
+ void DecDepComputeLevel();
+ /// A pure recursion return, no iteration.
+ bool IsInRecursionReturn() const { return bInRecursionReturn &&
+ !bInIterationReturn; }
+ void SetInRecursionReturn( bool b );
+ bool IsDoingRecursion() const { return bDoingRecursion; }
+ void SetDoingRecursion( bool b ) { bDoingRecursion = b; }
+
+ void Insert( ScFormulaCell* p, bool bOldRunning, const ScFormulaResult & rRes );
+
+ bool IsInIterationReturn() const { return bInIterationReturn; }
+ void SetInIterationReturn( bool b );
+ bool IsDoingIteration() const { return nIteration > 0; }
+ sal_uInt16 GetIteration() const { return nIteration; }
+ bool & GetConvergingReference() { return bConverging; }
+ void StartIteration();
+ void ResumeIteration();
+ void IncIteration();
+ void EndIteration();
+
+ const ScFormulaRecursionList::iterator& GetLastIterationStart() const { return aLastIterationStart; }
+ ScFormulaRecursionList::iterator GetIterationStart();
+ ScFormulaRecursionList::iterator GetIterationEnd();
+ /** Any return, recursion or iteration, iteration is always coupled with
+ recursion. */
+ bool IsInReturn() const { return bInRecursionReturn; }
+ const ScFormulaRecursionList& GetList() const { return aRecursionFormulas; }
+ ScFormulaRecursionList& GetList() { return aRecursionFormulas; }
+ ScRecursionInIterationStack& GetRecursionInIterationStack() { return aRecursionInIterationStack; }
+
+ void Clear();
+
+ /** Detects a simple cycle involving formula-groups and singleton formula-cells. */
+ bool PushFormulaGroup(ScFormulaCell* pCell);
+ void PopFormulaGroup();
+ bool AnyCycleMemberInDependencyEvalMode(const ScFormulaCell* pCell);
+ bool AnyParentFGInCycle();
+ void SetFormulaGroupDepEvalMode(bool bSet);
+ // When dependency computation detects a cycle, it may not compute proper cell values.
+ // This sets a flag that ScFormulaCell will use to avoid setting those new values
+ // and resetting the dirty flag, until the dependency computation bails out.
+ void AbortDependencyComputation();
+ bool IsAbortingDependencyComputation() const { return bAbortingDependencyComputation; }
+
+ void AddTemporaryGroupCell(ScFormulaCell* cell);
+ void CleanTemporaryGroupCells();
+
+ void SetFormulaGroupSet(o3tl::sorted_vector<ScFormulaCellGroup*>* pSet) { pFGSet = pSet; }
+ bool HasFormulaGroupSet() const { return pFGSet != nullptr; }
+ bool CheckFGIndependence(ScFormulaCellGroup* pFG);
+ void SetGroupsIndependent(bool bSet) { bGroupsIndependent = bSet; }
+ bool AreGroupsIndependent() { return bGroupsIndependent; }
+};
+
+/** A class to wrap ScRecursionHelper::PushFormulaGroup(),
+ ScRecursionHelper::PopFormulaGroup() and make these calls
+ exception safe. */
+class ScFormulaGroupCycleCheckGuard
+{
+ ScRecursionHelper& mrRecHelper;
+ bool mbShouldPop;
+public:
+ ScFormulaGroupCycleCheckGuard() = delete;
+ ScFormulaGroupCycleCheckGuard(ScRecursionHelper& rRecursionHelper, ScFormulaCell* pCell);
+ ~ScFormulaGroupCycleCheckGuard();
+
+};
+
+class ScFormulaGroupDependencyComputeGuard
+{
+ ScRecursionHelper& mrRecHelper;
+public:
+ ScFormulaGroupDependencyComputeGuard() = delete;
+ ScFormulaGroupDependencyComputeGuard(ScRecursionHelper& rRecursionHelper);
+ ~ScFormulaGroupDependencyComputeGuard();
+};
+
+class ScCheckIndependentFGGuard
+{
+ ScRecursionHelper& mrRecHelper;
+ bool mbUsedFGSet;
+public:
+ ScCheckIndependentFGGuard() = delete;
+ ScCheckIndependentFGGuard(ScRecursionHelper& rRecursionHelper,
+ o3tl::sorted_vector<ScFormulaCellGroup*>* pSet);
+ ~ScCheckIndependentFGGuard();
+
+ bool AreGroupsIndependent();
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */