From 29f0b94f6bd9b9209f2701f476d2860688991a97 Mon Sep 17 00:00:00 2001 From: Ryan Holt Date: Thu, 12 Mar 2020 10:39:59 -0400 Subject: [PATCH] Fixed an issue in getExitSet() Fixed an issue that caused getExitSet() to return an incorrect result in certain configurations, leading to the unexpected exit of states unrelated to the active transition. fixes #193 --- src/uscxml/interpreter/FastMicroStep.cpp | 26 ++++++++++++++--------- src/uscxml/interpreter/LargeMicroStep.cpp | 26 ++++++++++++++--------- 2 files changed, 32 insertions(+), 20 deletions(-) diff --git a/src/uscxml/interpreter/FastMicroStep.cpp b/src/uscxml/interpreter/FastMicroStep.cpp index 78aada954..ed6238f5e 100644 --- a/src/uscxml/interpreter/FastMicroStep.cpp +++ b/src/uscxml/interpreter/FastMicroStep.cpp @@ -217,21 +217,27 @@ std::pair FastMicroStep::getExitSet(const Transition* transi statesToExit.first = domainState->documentOrder + 1; // do not include domain itself // end of exit set - XERCESC_NS::DOMElement* sibling = domainState->element->getNextElementSibling(); - while(sibling && !isState(sibling)) - sibling = sibling->getNextElementSibling(); - if (sibling) { - State* siblingState = (State*)sibling->getUserData(X("uscxmlState")); - statesToExit.second = siblingState->documentOrder - 1; - } else { - statesToExit.second = _states.size() - 1; + statesToExit.second = statesToExit.first; + + uint32_t second = statesToExit.first + 1; + + while (second < _states.size()) { + State *childState = _states[second]; + + if (childState->ancestors[domain]) { + statesToExit.second = second; + } else { + break; + } + + second++; } + _exitSetCache[transition->postFixOrder] = statesToExit; - return statesToExit; } + return _exitSetCache[transition->postFixOrder]; } - uint32_t FastMicroStep::getTransitionDomain(const Transition* transition) { size_t i, j; if (!transition->target.any()) diff --git a/src/uscxml/interpreter/LargeMicroStep.cpp b/src/uscxml/interpreter/LargeMicroStep.cpp index a6d90f4d1..ae3193c60 100644 --- a/src/uscxml/interpreter/LargeMicroStep.cpp +++ b/src/uscxml/interpreter/LargeMicroStep.cpp @@ -1319,21 +1319,27 @@ std::pair LargeMicroStep::getExitSet(const Transition* trans statesToExit.first = domainState->documentOrder + 1; // do not include domain itself // end of exit set - XERCESC_NS::DOMElement* sibling = domainState->element->getNextElementSibling(); - while(sibling && !isState(sibling)) - sibling = sibling->getNextElementSibling(); - if (sibling) { - State* siblingState = (State*)sibling->getUserData(X("uscxmlState")); - statesToExit.second = siblingState->documentOrder - 1; - } else { - statesToExit.second = _states.size() - 1; + statesToExit.second = statesToExit.first; + + uint32_t second = statesToExit.first + 1; + + while (second < _states.size()) { + State *childState = _states[second]; + + if (childState->ancestors.find(domainState) != childState->ancestors.end()) { + statesToExit.second = second; + } else { + break; + } + + second++; } + _exitSetCache[transition->postFixOrder] = statesToExit; - return statesToExit; } + return _exitSetCache[transition->postFixOrder]; } - uint32_t LargeMicroStep::getTransitionDomain(const Transition* transition) { if (transition->target.size() == 0) return std::numeric_limits::max();