diff --git a/sources/OpenMcdf/CFStorage.cs b/sources/OpenMcdf/CFStorage.cs index 50be4405..10db29c2 100644 --- a/sources/OpenMcdf/CFStorage.cs +++ b/sources/OpenMcdf/CFStorage.cs @@ -409,34 +409,23 @@ public void VisitEntries(Action action, bool recursive) { CheckDisposed(); - if (action != null) - { - List subStorages - = new List(); - - Action internalAction = - delegate (IRBNode targetNode) - { - IDirectoryEntry d = targetNode as IDirectoryEntry; - if (d.StgType == StgType.StgStream) - action(new CFStream(CompoundFile, d)); - else - action(new CFStorage(CompoundFile, d)); + if (action is null) + return; // TODO: Reorder and throw ArgumentNullException in v3 - if (d.Child != DirectoryEntry.NOSTREAM) - subStorages.Add(targetNode); + Stack stack = new(); + stack.Push(this); - return; - }; - - Children.VisitTree(internalAction); - - if (recursive && subStorages.Count > 0) + while (stack.Count > 0) + { + CFItem current = stack.Pop(); + if (current is CFStorage storage) { - foreach (IRBNode n in subStorages) + foreach (IDirectoryEntry de in storage.Children.Cast()) { - IDirectoryEntry d = n as IDirectoryEntry; - new CFStorage(CompoundFile, d).VisitEntries(action, recursive); + CFItem item = de.StgType == StgType.StgStream ? new CFStream(CompoundFile, de) : new CFStorage(CompoundFile, de); + action(item); + if (recursive) + stack.Push(item); } } } diff --git a/sources/OpenMcdf/RBTree/RBTreeEnumerator.cs b/sources/OpenMcdf/RBTree/RBTreeEnumerator.cs index 7d23ec63..478757d6 100644 --- a/sources/OpenMcdf/RBTree/RBTreeEnumerator.cs +++ b/sources/OpenMcdf/RBTree/RBTreeEnumerator.cs @@ -8,31 +8,47 @@ public partial class RBTree // TODO: Make internal in v3 (can seal in v2 since constructor is internal) public sealed class RBTreeEnumerator : IEnumerator { - private readonly List list = new(); - int position = -1; + private readonly IRBNode root; + private readonly Stack stack = new(); internal RBTreeEnumerator(RBTree tree) { - tree.VisitTree(item => list.Add(item)); + root = tree.Root; + PushLeft(root); } public void Dispose() { } - public IRBNode Current => list[position]; + public IRBNode Current { get; private set; } - object IEnumerator.Current => list[position]; + object IEnumerator.Current => Current; public bool MoveNext() { - position++; - return position < list.Count; + if (stack.Count == 0) + return false; + + Current = stack.Pop(); + PushLeft(Current.Right); + return true; } public void Reset() { - position = -1; + Current = null; + stack.Clear(); + PushLeft(root); + } + + private void PushLeft(IRBNode node) + { + while (node is not null) + { + stack.Push(node); + node = node.Left; + } } } }