mirror of
https://github.com/Open-Cascade-SAS/OCCT.git
synced 2026-09-07 21:28:11 +08:00
Modeling - Refactor TopExp_Explorer to use NCollection_LocalArray for stack management (#1181)
- Replaced `TopExp_Explorer`’s `NCollection_Vector`-based stack with `NCollection_LocalArray` + explicit stack-top index management. - Extended `NCollection_LocalArray` to support non-trivial element types using placement-new, move semantics, and explicit destruction. - Added GTests for `NCollection_LocalArray` covering non-trivial element lifetime and realloc/move scenarios.
This commit is contained in:
@@ -38,8 +38,7 @@ inline bool isMoreComplex(const TopAbs_ShapeEnum theType, const TopAbs_ShapeEnum
|
||||
//=================================================================================================
|
||||
|
||||
TopExp_Explorer::TopExp_Explorer() noexcept
|
||||
: myStack(20),
|
||||
toFind(TopAbs_SHAPE),
|
||||
: toFind(TopAbs_SHAPE),
|
||||
toAvoid(TopAbs_SHAPE),
|
||||
hasMore(false)
|
||||
{
|
||||
@@ -50,8 +49,7 @@ TopExp_Explorer::TopExp_Explorer() noexcept
|
||||
TopExp_Explorer::TopExp_Explorer(const TopoDS_Shape& S,
|
||||
const TopAbs_ShapeEnum ToFind,
|
||||
const TopAbs_ShapeEnum ToAvoid)
|
||||
: myStack(20),
|
||||
toFind(ToFind),
|
||||
: toFind(ToFind),
|
||||
toAvoid(ToAvoid),
|
||||
hasMore(false)
|
||||
{
|
||||
@@ -109,7 +107,7 @@ void TopExp_Explorer::Init(const TopoDS_Shape& S,
|
||||
|
||||
void TopExp_Explorer::Next()
|
||||
{
|
||||
if (myStack.IsEmpty())
|
||||
if (myStackTop < 0)
|
||||
{
|
||||
TopAbs_ShapeEnum ty = myShape.ShapeType();
|
||||
|
||||
@@ -125,15 +123,15 @@ void TopExp_Explorer::Next()
|
||||
}
|
||||
else
|
||||
{
|
||||
myStack.Append(TopoDS_Iterator(myShape));
|
||||
pushIterator(TopoDS_Iterator(myShape));
|
||||
}
|
||||
}
|
||||
else
|
||||
myStack.ChangeLast().Next();
|
||||
myStack[myStackTop].Next();
|
||||
|
||||
for (;;)
|
||||
{
|
||||
TopoDS_Iterator& aTopIter = myStack.ChangeLast();
|
||||
TopoDS_Iterator& aTopIter = myStack[myStackTop];
|
||||
|
||||
if (aTopIter.More())
|
||||
{
|
||||
@@ -147,8 +145,8 @@ void TopExp_Explorer::Next()
|
||||
}
|
||||
else if (isMoreComplex(ty, toFind) && !shouldAvoid(ty, toAvoid))
|
||||
{
|
||||
myStack.Append(TopoDS_Iterator(aShapTop));
|
||||
// aTopIter reference is now invalid after Append
|
||||
pushIterator(TopoDS_Iterator(aShapTop));
|
||||
// aTopIter reference is now invalid after push
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -157,10 +155,10 @@ void TopExp_Explorer::Next()
|
||||
}
|
||||
else
|
||||
{
|
||||
myStack.EraseLast();
|
||||
if (myStack.IsEmpty())
|
||||
popIterator();
|
||||
if (myStackTop < 0)
|
||||
break;
|
||||
myStack.ChangeLast().Next();
|
||||
myStack[myStackTop].Next();
|
||||
}
|
||||
}
|
||||
hasMore = false;
|
||||
@@ -170,20 +168,46 @@ void TopExp_Explorer::Next()
|
||||
|
||||
const TopoDS_Shape& TopExp_Explorer::Current() const noexcept
|
||||
{
|
||||
return myStack.IsEmpty() ? myShape : myStack.Last().Value();
|
||||
return myStackTop < 0 ? myShape : myStack[myStackTop].Value();
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
int TopExp_Explorer::Depth() const noexcept
|
||||
{
|
||||
return myStack.Length();
|
||||
return myStackTop + 1;
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
void TopExp_Explorer::Clear()
|
||||
{
|
||||
hasMore = false;
|
||||
myStack.Clear();
|
||||
// Shrink to 0 - NCollection_LocalArray destroys all live elements.
|
||||
if (myStack.Size() > 0)
|
||||
myStack.Reallocate(0);
|
||||
myStackTop = -1;
|
||||
hasMore = false;
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
void TopExp_Explorer::pushIterator(TopoDS_Iterator&& theIter)
|
||||
{
|
||||
++myStackTop;
|
||||
if (static_cast<size_t>(myStackTop) >= myStack.Size())
|
||||
{
|
||||
const size_t aNewSize =
|
||||
std::max<size_t>(myStack.Size() * 2, static_cast<size_t>(THE_INLINE_STACK_SIZE));
|
||||
myStack.Reallocate(aNewSize, true);
|
||||
}
|
||||
myStack[myStackTop] = std::move(theIter);
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
|
||||
void TopExp_Explorer::popIterator()
|
||||
{
|
||||
// Reset the popped iterator to release shape references immediately.
|
||||
myStack[myStackTop] = TopoDS_Iterator();
|
||||
--myStackTop;
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
#ifndef _TopExp_Explorer_HeaderFile
|
||||
#define _TopExp_Explorer_HeaderFile
|
||||
|
||||
#include <NCollection_Vector.hxx>
|
||||
#include <NCollection_LocalArray.hxx>
|
||||
#include <TopAbs.hxx>
|
||||
#include <TopoDS_Iterator.hxx>
|
||||
#include <TopoDS_Shape.hxx>
|
||||
@@ -139,11 +139,22 @@ public:
|
||||
Standard_EXPORT ~TopExp_Explorer();
|
||||
|
||||
private:
|
||||
NCollection_Vector<TopoDS_Iterator> myStack;
|
||||
TopoDS_Shape myShape;
|
||||
TopAbs_ShapeEnum toFind;
|
||||
TopAbs_ShapeEnum toAvoid;
|
||||
bool hasMore;
|
||||
//! Push a new iterator onto the stack (placement new on first use, assign on reuse).
|
||||
void pushIterator(TopoDS_Iterator&& theIter);
|
||||
|
||||
//! Pop the top iterator (explicit destructor call).
|
||||
void popIterator();
|
||||
|
||||
static constexpr int THE_INLINE_STACK_SIZE =
|
||||
20; //!< Inline stack capacity (covers all topology depths)
|
||||
|
||||
NCollection_LocalArray<TopoDS_Iterator, THE_INLINE_STACK_SIZE>
|
||||
myStack; //!< DFS stack (lazy allocation)
|
||||
int myStackTop = -1; //!< Top of stack index (-1 = empty)
|
||||
TopoDS_Shape myShape;
|
||||
TopAbs_ShapeEnum toFind;
|
||||
TopAbs_ShapeEnum toAvoid;
|
||||
bool hasMore;
|
||||
};
|
||||
|
||||
#endif // _TopExp_Explorer_HeaderFile
|
||||
|
||||
Reference in New Issue
Block a user