public static Result IterateDirectoryRecursively(IFileSystem fs, U8Span rootPath, FsIterationTask onEnterDir, FsIterationTask onExitDir, FsIterationTask onFile) { DirectoryEntry entry = default; Span <byte> workPath = stackalloc byte[PathTools.MaxPathLength + 1]; return(IterateDirectoryRecursively(fs, rootPath, workPath, ref entry, onEnterDir, onExitDir, onFile)); }
private static Result IterateDirectoryRecursivelyImpl(IFileSystem fs, Span <byte> workPath, ref DirectoryEntry dirEntry, FsIterationTask onEnterDir, FsIterationTask onExitDir, FsIterationTask onFile) { Result rc = fs.OpenDirectory(out IDirectory dir, new U8Span(workPath), OpenDirectoryMode.All); if (rc.IsFailure()) { return(rc); } int parentLen = StringUtils.GetLength(workPath); // Read and handle entries. while (true) { // Read a single entry. rc = dir.Read(out long readCount, SpanHelpers.AsSpan(ref dirEntry)); if (rc.IsFailure()) { return(rc); } // If we're out of entries, we're done. if (readCount == 0) { break; } // Validate child path size. int childNameLen = StringUtils.GetLength(dirEntry.Name); bool isDir = dirEntry.Type == DirectoryEntryType.Directory; int separatorSize = isDir ? 1 : 0; if (parentLen + childNameLen + separatorSize >= workPath.Length) { return(ResultFs.TooLongPath.Log()); } // Set child path. StringUtils.Concat(workPath, dirEntry.Name); { if (isDir) { // Enter directory. rc = onEnterDir(new U8Span(workPath), ref dirEntry); if (rc.IsFailure()) { return(rc); } // Append separator, recurse. StringUtils.Concat(workPath, DirectorySeparator); rc = IterateDirectoryRecursivelyImpl(fs, workPath, ref dirEntry, onEnterDir, onExitDir, onFile); if (rc.IsFailure()) { return(rc); } // Exit directory. rc = onExitDir(new U8Span(workPath), ref dirEntry); if (rc.IsFailure()) { return(rc); } } else { // Call file handler. rc = onFile(new U8Span(workPath), ref dirEntry); if (rc.IsFailure()) { return(rc); } } } // Restore parent path. workPath[parentLen] = StringTraits.NullTerminator; } return(Result.Success); }
public static Result IterateDirectoryRecursively(IFileSystem fs, FsIterationTask onEnterDir, FsIterationTask onExitDir, FsIterationTask onFile) { return(IterateDirectoryRecursively(fs, RootPath, onEnterDir, onExitDir, onFile)); }
public static Result IterateDirectoryRecursively(IFileSystem fs, U8Span rootPath, Span <byte> workPath, ref DirectoryEntry dirEntry, FsIterationTask onEnterDir, FsIterationTask onExitDir, FsIterationTask onFile) { Abort.DoAbortUnless(workPath.Length >= PathTool.EntryNameLengthMax + 1); // Get size of the root path. int rootPathLen = StringUtils.GetLength(rootPath, PathTool.EntryNameLengthMax + 1); if (rootPathLen > PathTool.EntryNameLengthMax) { return(ResultFs.TooLongPath.Log()); } // Copy root path in, add a / if necessary. rootPath.Value.Slice(0, rootPathLen).CopyTo(workPath); if (!PathTool.IsSeparator(workPath[rootPathLen - 1])) { workPath[rootPathLen++] = StringTraits.DirectorySeparator; } // Make sure the result path is still valid. if (rootPathLen > PathTool.EntryNameLengthMax) { return(ResultFs.TooLongPath.Log()); } workPath[rootPathLen] = StringTraits.NullTerminator; return(IterateDirectoryRecursivelyImpl(fs, workPath, ref dirEntry, onEnterDir, onExitDir, onFile)); }