diff --git a/sources/OpenMcdf/CFStorage.cs b/sources/OpenMcdf/CFStorage.cs index 0a238fc7..50be4405 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 560fef8e..bf5de1c0 100644 --- a/sources/OpenMcdf/CompoundFile.cs +++ b/sources/OpenMcdf/CompoundFile.cs @@ -1500,45 +1500,14 @@ 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]); - //bst = DoLoadChildrenTrusted(directoryEntries[sid]); - - //bst.Print(); - //bst.Print(); - //Trace.WriteLine("#### After rethreading"); - - return bst; - } - - private RBTree DoLoadChildrenTrusted(IDirectoryEntry de) - { - RBTree bst = null; - - if (de.Child != DirectoryEntry.NOSTREAM) - { - bst = new RBTree(directoryEntries[de.Child]); - } - + RBTree bst = new(); + List levelSIDs = new List(); + LoadChildren(bst, entry.Child, levelSIDs); return bst; } - private void DoLoadChildren(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]); - } - } - private static void NullifyChildNodes(IDirectoryEntry de) { de.Parent = null; @@ -1546,95 +1515,48 @@ 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(); - - if (de.LeftSibling != DirectoryEntry.NOSTREAM) - { - // If there are more left siblings load them... - DoLoadSiblings(bst, directoryEntries[de.LeftSibling], levelSIDs); - } - - if (de.RightSibling != DirectoryEntry.NOSTREAM) - { - levelSIDs.Add(de.RightSibling); + levelSIDs.Add(de.SID); - // If there are more right siblings load them... - DoLoadSiblings(bst, directoryEntries[de.RightSibling], levelSIDs); - } - } - - private void DoLoadSiblings(RBTree bst, IDirectoryEntry de, List levelSIDs) - { - if (ValidateSibling(de.LeftSibling, levelSIDs)) + if (de.StgType == StgType.StgInvalid) { - levelSIDs.Add(de.LeftSibling); - - // 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}]"); + return; } - if (ValidateSibling(de.RightSibling, levelSIDs)) + 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"); + return; } + LoadChildren(bst, de.LeftSibling, levelSIDs); + LoadChildren(bst, de.RightSibling, levelSIDs); NullifyChildNodes(de); bst.Insert(de); } - private bool ValidateSibling(int sid, List levelSIDs) + private void LoadChildren(RBTree bst, 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; - return true; //No fault condition encountered for sid being validated + // if this siblings id does not overflow current list + if (sid >= directoryEntries.Count) + { + if (ValidationExceptionEnabled) + throw new CFCorruptedFileException($"A Directory Entry references the non-existent sid number {sid}"); + return; } - return false; + if (levelSIDs.Contains(sid)) + throw new CFCorruptedFileException("Cyclic reference of directory item"); + + IDirectoryEntry de = directoryEntries[sid]; + LoadChildren(bst, de, levelSIDs); } ///