diff --git a/sources/OpenMcdf/CFStorage.cs b/sources/OpenMcdf/CFStorage.cs index 0a238fc..50be440 100644 --- a/sources/OpenMcdf/CFStorage.cs +++ b/sources/OpenMcdf/CFStorage.cs @@ -53,16 +53,7 @@ internal RBTree Children get { // Lazy loading of children tree. - if (children == null) - { - //if (this.CompoundFile.HasSourceStream) - //{ - children = LoadChildren(DirEntry.SID); - //} - //else - children ??= new RBTree(); - } - + children ??= LoadChildren(DirEntry); return children; } } @@ -81,15 +72,10 @@ internal CFStorage(CompoundFile compFile, IDirectoryEntry dirEntry) DirEntry = dirEntry; } - private RBTree LoadChildren(int SID) + private RBTree LoadChildren(IDirectoryEntry directoryEntry) { - RBTree childrenTree = CompoundFile.GetChildrenTree(SID); - - if (childrenTree.Root != null) - DirEntry.Child = (childrenTree.Root as IDirectoryEntry).SID; - else - DirEntry.Child = DirectoryEntry.NOSTREAM; - + RBTree childrenTree = CompoundFile.GetChildrenTree(directoryEntry); + DirEntry.Child = childrenTree.Root == null ? DirectoryEntry.NOSTREAM : ((IDirectoryEntry)childrenTree.Root).SID; return childrenTree; } @@ -566,9 +552,7 @@ public void RenameItem(string oldItemName, string newItemName) else throw new CFItemNotFound("Item " + oldItemName + " not found in Storage"); children = null; - children = LoadChildren(DirEntry.SID); //Rethread - - children ??= new RBTree(); + children = LoadChildren(DirEntry); // Rethread } } } diff --git a/sources/OpenMcdf/CompoundFile.cs b/sources/OpenMcdf/CompoundFile.cs index 560fef8..baf7ef1 100644 --- a/sources/OpenMcdf/CompoundFile.cs +++ b/sources/OpenMcdf/CompoundFile.cs @@ -1500,12 +1500,12 @@ internal List GetSectorChain(int secID, SectorType chainType) // node.Value.DirEntry.RightSibling = from.DirEntry.RightSibling; //} - internal RBTree GetChildrenTree(int sid) + internal RBTree GetChildrenTree(IDirectoryEntry entry) { RBTree bst = new RBTree(); // Load children from their original tree. - DoLoadChildren(bst, directoryEntries[sid]); + LoadChildren(bst, entry); //bst = DoLoadChildrenTrusted(directoryEntries[sid]); //bst.Print(); @@ -1527,15 +1527,16 @@ private RBTree DoLoadChildrenTrusted(IDirectoryEntry de) return bst; } - private void DoLoadChildren(RBTree bst, IDirectoryEntry de) + private void LoadChildren(RBTree bst, IDirectoryEntry de) { if (de.Child != DirectoryEntry.NOSTREAM) { - if (directoryEntries[de.Child].StgType == StgType.StgInvalid) return; - - LoadSiblings(bst, directoryEntries[de.Child]); - NullifyChildNodes(directoryEntries[de.Child]); - bst.Insert(directoryEntries[de.Child]); + IDirectoryEntry child = directoryEntries[de.Child]; + if (child.StgType != StgType.StgInvalid) + { + List levelSIDs = new List(); + LoadChildren(bst, child, levelSIDs); + } } } @@ -1546,95 +1547,51 @@ private static void NullifyChildNodes(IDirectoryEntry de) de.Right = null; } - // Doubling methods allows iterative behavior while avoiding - // to insert duplicate items - private void LoadSiblings(RBTree bst, IDirectoryEntry de) + private void LoadChildren(RBTree bst, IDirectoryEntry de, List levelSIDs) { - List levelSIDs = new List(); + levelSIDs.Add(de.SID); - if (de.LeftSibling != DirectoryEntry.NOSTREAM) + if (de.StgType == StgType.StgInvalid) { - // If there are more left siblings load them... - DoLoadSiblings(bst, directoryEntries[de.LeftSibling], levelSIDs); + if (ValidationExceptionEnabled) + throw new CFCorruptedFileException($"A Directory Entry has a valid reference to an Invalid Storage Type directory [{de.SID}]"); } - if (de.RightSibling != DirectoryEntry.NOSTREAM) + if (!Enum.IsDefined(typeof(StgType), de.StgType)) { - levelSIDs.Add(de.RightSibling); - - // If there are more right siblings load them... - DoLoadSiblings(bst, directoryEntries[de.RightSibling], levelSIDs); + if (ValidationExceptionEnabled) + throw new CFCorruptedFileException("A Directory Entry has an invalid Storage Type"); } - } - private void DoLoadSiblings(RBTree bst, IDirectoryEntry de, List levelSIDs) - { - if (ValidateSibling(de.LeftSibling, levelSIDs)) - { - levelSIDs.Add(de.LeftSibling); + // If there are more left siblings load them... + if (SiblingIsValid(de.LeftSibling, levelSIDs)) + LoadChildren(bst, directoryEntries[de.LeftSibling], levelSIDs); - // If there are more left siblings load them... - DoLoadSiblings(bst, directoryEntries[de.LeftSibling], levelSIDs); - } - - if (ValidateSibling(de.RightSibling, levelSIDs)) - { - levelSIDs.Add(de.RightSibling); - - // If there are more right siblings load them... - DoLoadSiblings(bst, directoryEntries[de.RightSibling], levelSIDs); - } + // If there are more right siblings load them... + if (SiblingIsValid(de.RightSibling, levelSIDs)) + LoadChildren(bst, directoryEntries[de.RightSibling], levelSIDs); NullifyChildNodes(de); bst.Insert(de); } - private bool ValidateSibling(int sid, List levelSIDs) + private bool SiblingIsValid(int sid, List levelSIDs) { - if (sid != DirectoryEntry.NOSTREAM) - { - // if this siblings id does not overflow current list - if (sid >= directoryEntries.Count) - { - if (ValidationExceptionEnabled) - { - //this.Close(); - throw new CFCorruptedFileException("A Directory Entry references the non-existent sid number " + sid.ToString()); - } - else - return false; - } - - //if this sibling is valid... - if (directoryEntries[sid].StgType == StgType.StgInvalid) - { - if (ValidationExceptionEnabled) - { - //this.Close(); - throw new CFCorruptedFileException("A Directory Entry has a valid reference to an Invalid Storage Type directory [" + sid + "]"); - } - else - return false; - } - - if (!Enum.IsDefined(typeof(StgType), directoryEntries[sid].StgType)) - { - if (ValidationExceptionEnabled) - { - //this.Close(); - throw new CFCorruptedFileException("A Directory Entry has an invalid Storage Type"); - } - else - return false; - } - - if (levelSIDs.Contains(sid)) - throw new CFCorruptedFileException("Cyclic reference of directory item"); + if (sid == DirectoryEntry.NOSTREAM) + return false; - return true; //No fault condition encountered for sid being validated + // if this siblings id does not overflow current list + if (sid >= directoryEntries.Count) + { + return ValidationExceptionEnabled + ? throw new CFCorruptedFileException($"A Directory Entry references the non-existent sid number {sid}") + : false; } - return false; + if (levelSIDs.Contains(sid)) + throw new CFCorruptedFileException("Cyclic reference of directory item"); + + return true; // No fault condition encountered for sid being validated } ///