diff --git a/src/LibHac/FsSystem/SaveDataFileSystemCacheRegisterBase.cs b/src/LibHac/FsSystem/SaveDataFileSystemCacheRegisterBase.cs new file mode 100644 index 00000000..20d7f42e --- /dev/null +++ b/src/LibHac/FsSystem/SaveDataFileSystemCacheRegisterBase.cs @@ -0,0 +1,181 @@ +using LibHac.Common; +using LibHac.Diag; +using LibHac.Fs; +using LibHac.Fs.Fsa; +using LibHac.FsSystem.Save; + +namespace LibHac.FsSystem +{ + /// + /// Wraps a save data . + /// Upon disposal the base file system is returned to the provided . + /// + /// The type of the base file system. Must be one of , + /// or . + public class SaveDataFileSystemCacheRegisterBase : IFileSystem where T : IFileSystem + { + private ReferenceCountedDisposable _baseFileSystem; + private ISaveDataFileSystemCacheManager _cacheManager; + + public SaveDataFileSystemCacheRegisterBase(ref ReferenceCountedDisposable baseFileSystem, + ISaveDataFileSystemCacheManager cacheManager) + { + Assert.SdkRequires(typeof(T) == typeof(SaveDataFileSystem) || + typeof(T) == typeof(ApplicationTemporaryFileSystem) || + typeof(T) == typeof(DirectorySaveDataFileSystem)); + + _baseFileSystem = Shared.Move(ref baseFileSystem); + _cacheManager = cacheManager; + } + + + public static ReferenceCountedDisposable CreateShared( + ReferenceCountedDisposable baseFileSystem, ISaveDataFileSystemCacheManager cacheManager) + { + IFileSystem baseFsTarget = baseFileSystem.Target; + + switch (baseFsTarget) + { + case SaveDataFileSystem: + { + ReferenceCountedDisposable castedFs = + baseFileSystem.AddReference(); + + return new ReferenceCountedDisposable( + new SaveDataFileSystemCacheRegisterBase(ref castedFs, cacheManager)); + } + case ApplicationTemporaryFileSystem: + { + ReferenceCountedDisposable castedFs = + baseFileSystem.AddReference(); + + return new ReferenceCountedDisposable( + new SaveDataFileSystemCacheRegisterBase(ref castedFs, + cacheManager)); + } + case DirectorySaveDataFileSystem: + { + ReferenceCountedDisposable castedFs = + baseFileSystem.AddReference(); + + return new ReferenceCountedDisposable( + new SaveDataFileSystemCacheRegisterBase(ref castedFs, + cacheManager)); + } + default: + Assert.SdkAssert(false, "Invalid save data file system type."); + return null; + } + } + + protected override void Dispose(bool disposing) + { + if (_baseFileSystem is null) + return; + + if (disposing) + { + if (typeof(T) == typeof(SaveDataFileSystem)) + { + _cacheManager.Register( + (ReferenceCountedDisposable)(object)_baseFileSystem); + } + else if (typeof(T) == typeof(ApplicationTemporaryFileSystem)) + { + _cacheManager.Register( + (ReferenceCountedDisposable)(object)_baseFileSystem); + } + else if (typeof(T) == typeof(DirectorySaveDataFileSystem)) + { + _cacheManager.Register( + (ReferenceCountedDisposable)(object)_baseFileSystem); + } + + _baseFileSystem.Dispose(); + _baseFileSystem = null; + } + + base.Dispose(disposing); + } + + protected override Result DoOpenFile(out IFile file, U8Span path, OpenMode mode) + { + return _baseFileSystem.Target.OpenFile(out file, path, mode); + } + + protected override Result DoOpenDirectory(out IDirectory directory, U8Span path, OpenDirectoryMode mode) + { + return _baseFileSystem.Target.OpenDirectory(out directory, path, mode); + } + + protected override Result DoGetEntryType(out DirectoryEntryType entryType, U8Span path) + { + return _baseFileSystem.Target.GetEntryType(out entryType, path); + } + + protected override Result DoCreateFile(U8Span path, long size, CreateFileOptions option) + { + return _baseFileSystem.Target.CreateFile(path, size, option); + } + + protected override Result DoDeleteFile(U8Span path) + { + return _baseFileSystem.Target.DeleteFile(path); + } + + protected override Result DoCreateDirectory(U8Span path) + { + return _baseFileSystem.Target.CreateDirectory(path); + } + + protected override Result DoDeleteDirectory(U8Span path) + { + return _baseFileSystem.Target.DeleteDirectory(path); + } + + protected override Result DoDeleteDirectoryRecursively(U8Span path) + { + return _baseFileSystem.Target.DeleteDirectoryRecursively(path); + } + + protected override Result DoCleanDirectoryRecursively(U8Span path) + { + return _baseFileSystem.Target.CleanDirectoryRecursively(path); + } + + protected override Result DoRenameFile(U8Span oldPath, U8Span newPath) + { + return _baseFileSystem.Target.RenameFile(oldPath, newPath); + } + + protected override Result DoRenameDirectory(U8Span oldPath, U8Span newPath) + { + return _baseFileSystem.Target.RenameDirectory(oldPath, newPath); + } + + protected override Result DoCommit() + { + return _baseFileSystem.Target.Commit(); + } + + protected override Result DoCommitProvisionally(long counter) + { + return _baseFileSystem.Target.CommitProvisionally(counter); + } + + protected override Result DoRollback() + { + return _baseFileSystem.Target.Rollback(); + } + + protected override Result DoGetFreeSpaceSize(out long freeSpace, U8Span path) + { + return _baseFileSystem.Target.GetFreeSpaceSize(out freeSpace, path); + } + + protected override Result DoGetTotalSpaceSize(out long totalSpace, U8Span path) + { + return _baseFileSystem.Target.GetTotalSpaceSize(out totalSpace, path); + } + } +} \ No newline at end of file