/*---------------------------------------------------------------------------* Project: Horizon File: fslow_IArchive.h Copyright (C)2009 Nintendo Co., Ltd. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. $Rev: 25433 $ *---------------------------------------------------------------------------*/ #ifndef NN_FSLOW_FSLOW_ARCHIVEMAPFILESYSTEM_H_ #define NN_FSLOW_FSLOW_ARCHIVEMAPFILESYSTEM_H_ #include #include #include #pragma push #pragma diag_suppress 2817 // #2817-D: temporary used for conditional class rvalue result (C++ core issue #446 resolution) 対策 #include #pragma pop #include "fslow_IArchive.h" namespace nn { namespace fslow { template class ArchiveMapFileSystem { public: // スレッドセーフティ? typedef typename TFileSystemTypeInfo::Archive Archive; typedef typename TFileSystemTypeInfo::File File; typedef typename TFileSystemTypeInfo::Directory Directory; typedef typename TFileSystemTypeInfo::FileHandle FileHandle; typedef typename TFileSystemTypeInfo::DirectoryHandle DirectoryHandle; typedef typename TFileSystemTypeInfo::Path Path; typedef typename TFileSystemTypeInfo::DirectoryEntry DirectoryEntry; typedef TArchiveHandleTable ArchiveHandleTable; typedef typename ArchiveHandleTable::Handle ArchiveHandle; // Self に CRTP で要求するインターフェイス // ArchiveHandleTable& GetHandleTable(); // Result RegisterToNameMap(ArchiveName, ArchiveHandle); // void UnregisterFromNameMap(ArchiveName); // ArchiveName GetArchiveName(Path); // Path GetPathString(Path); private: Self& GetSelf() { return static_cast(*this); } const Self& GetSelf() const { return static_cast(*this); } typedef typename ArchiveHandleTable::Accessor Accessor; public: Result AddArchive(const ArchiveName& name, Archive archive) { ArchiveHandle handle = GetSelf().GetHandleTable().Register(archive); if (!handle) { // TODO: 適切な Result return nn::fs::ResultOutOfMemory(); } Result result = GetSelf().RegisterToNameMap(name, handle); if (result.IsFailure()) { GetSelf().GetHandleTable().Unregister(handle); } return result; } Result RemoveArchive(const ArchiveName& name) { ArchiveHandle handle; NN_UTIL_RETURN_IF_FAILED(GetSelf().GetArchiveHandle(&handle, name)); GetSelf().UnregisterFromNameMap(name); GetSelf().GetHandleTable().Unregister(handle); return nn::ResultSuccess(); } Result OpenFile(FileHandle* pOut, nn::fs::Transaction transaction, Path path, bit32 mode, nn::fs::Attributes attributes) { nn::fs::PathMark pathMark; pathMark.rawPathMark = 0; return OpenFile( pOut, transaction, path, pathMark, mode, attributes); } Result OpenFile(FileHandle* pOut, nn::fs::Transaction transaction, Path path, nn::fs::PathMark pathMark, bit32 mode, nn::fs::Attributes attributes) { ArchiveName name = GetSelf().GetArchiveName(path); if (!name.IsValid()) { return nn::fs::ResultInvalidPathFormat(); } ArchiveHandle handle; NN_UTIL_RETURN_IF_FAILED(GetSelf().GetArchiveHandle(&handle, name)); File file; { Accessor acc(GetSelf().GetHandleTable(), handle); if (!acc) { // TODO: この Result でいい? return nn::fs::ResultArchiveNotFound(); } NN_UTIL_RETURN_IF_FAILED(acc->OpenFile(&file, transaction, GetSelf().GetPathString(Move(path)), pathMark, mode, attributes)); } *pOut = FileHandle(handle, file); return nn::ResultSuccess(); } Result ReadFile(s32* pOut, const FileHandle& handle, s64 offset, void* buffer, size_t size) { Accessor acc(GetSelf().GetHandleTable(), handle.archiveHandle); if (!acc) { // TODO: この Result でいい? return nn::fs::ResultArchiveNotFound(); } return handle.p->ReadBytes(pOut, offset, buffer, size); } Result WriteFile(s32* pOut, const FileHandle& handle, s64 offset, const void* buffer, size_t size) { Accessor acc(GetSelf().GetHandleTable(), handle.archiveHandle); if (!acc) { // TODO: この Result でいい? return nn::fs::ResultArchiveNotFound(); } return handle.p->WriteBytes(pOut, offset, buffer, size, true); } Result GetFileSize(s64* pOut, const FileHandle& handle) { Accessor acc(GetSelf().GetHandleTable(), handle.archiveHandle); if (!acc) { // TODO: この Result でいい? return nn::fs::ResultArchiveNotFound(); } return handle.p->GetSize(pOut); } Result SetFileSize(const FileHandle& handle, s64 size) { Accessor acc(GetSelf().GetHandleTable(), handle.archiveHandle); if (!acc) { // TODO: この Result でいい? return nn::fs::ResultArchiveNotFound(); } return handle.p->SetSize(size); } Result CloseFile(const FileHandle& handle) { Accessor acc(GetSelf().GetHandleTable(), handle.archiveHandle); if (!acc) { // TODO: この Result でいい? return nn::fs::ResultArchiveNotFound(); } Result result = handle.p->Close(); acc->FreeFileObject(handle.p); return result; } Result OpenDirectory(DirectoryHandle* pOut, Path path) { ArchiveName name = GetSelf().GetArchiveName(path); if (!name.IsValid()) { return nn::fs::ResultInvalidPathFormat(); } ArchiveHandle handle; NN_UTIL_RETURN_IF_FAILED(GetSelf().GetArchiveHandle(&handle, name)); Directory directory; { Accessor acc(GetSelf().GetHandleTable(), handle); if (!acc) { // TODO: この Result でいい? return nn::fs::ResultArchiveNotFound(); } NN_UTIL_RETURN_IF_FAILED(acc->OpenDirectory(&directory, GetSelf().GetPathString(Move(path)))); } *pOut = DirectoryHandle(handle, directory); return nn::ResultSuccess(); } Result ReadDirectory(s32* pNumEntriesOut, const DirectoryHandle& handle, DirectoryEntry entries[], s32 numEntries) { Accessor acc(GetSelf().GetHandleTable(), handle.archiveHandle); if (!acc) { // TODO: この Result でいい? return nn::fs::ResultArchiveNotFound(); } return handle.p->Read(pNumEntriesOut, entries, numEntries); } Result CloseDirectory(const DirectoryHandle& handle) { Accessor acc(GetSelf().GetHandleTable(), handle.archiveHandle); if (!acc) { // TODO: この Result でいい? return nn::fs::ResultArchiveNotFound(); } Result result = handle.p->Close(); acc->FreeDirectoryObject(handle.p); return result; } Result DeleteFile(nn::fs::Transaction transaction, Path path) { ArchiveName name = GetSelf().GetArchiveName(path); if (!name.IsValid()) { return nn::fs::ResultInvalidPathFormat(); } ArchiveHandle handle; NN_UTIL_RETURN_IF_FAILED(GetSelf().GetArchiveHandle(&handle, name)); { Accessor acc(GetSelf().GetHandleTable(), handle); if (!acc) { // TODO: この Result でいい? return nn::fs::ResultArchiveNotFound(); } NN_UTIL_RETURN_IF_FAILED(acc->DeleteFile(transaction, GetSelf().GetPathString(Move(path)))); } return nn::ResultSuccess(); } Result DeleteDirectory(nn::fs::Transaction transaction, Path path) { ArchiveName name = GetSelf().GetArchiveName(path); if (!name.IsValid()) { return nn::fs::ResultInvalidPathFormat(); } ArchiveHandle handle; NN_UTIL_RETURN_IF_FAILED(GetSelf().GetArchiveHandle(&handle, name)); { Accessor acc(GetSelf().GetHandleTable(), handle); if (!acc) { // TODO: この Result でいい? return nn::fs::ResultArchiveNotFound(); } NN_UTIL_RETURN_IF_FAILED(acc->DeleteDirectory(transaction, GetSelf().GetPathString(Move(path)))); } return nn::ResultSuccess(); } Result DeleteDirectoryRecursively(nn::fs::Transaction transaction, Path path) { ArchiveName name = GetSelf().GetArchiveName(path); if (!name.IsValid()) { return nn::fs::ResultInvalidPathFormat(); } ArchiveHandle handle; NN_UTIL_RETURN_IF_FAILED(GetSelf().GetArchiveHandle(&handle, name)); { Accessor acc(GetSelf().GetHandleTable(), handle); if (!acc) { // TODO: この Result でいい? return nn::fs::ResultArchiveNotFound(); } NN_UTIL_RETURN_IF_FAILED(acc->DeleteDirectoryRecursively(transaction, GetSelf().GetPathString(Move(path)))); } return nn::ResultSuccess(); } Result CreateDirectory(nn::fs::Transaction transaction, Path path, nn::fs::Attributes attributes) { ArchiveName name = GetSelf().GetArchiveName(path); if (!name.IsValid()) { return nn::fs::ResultInvalidPathFormat(); } ArchiveHandle handle; NN_UTIL_RETURN_IF_FAILED(GetSelf().GetArchiveHandle(&handle, name)); { Accessor acc(GetSelf().GetHandleTable(), handle); if (!acc) { // TODO: この Result でいい? return nn::fs::ResultArchiveNotFound(); } NN_UTIL_RETURN_IF_FAILED(acc->CreateDirectory(transaction, GetSelf().GetPathString(Move(path)), attributes)); } return nn::ResultSuccess(); } Result RenameFile(nn::fs::Transaction transaction, Path oldPath, Path newPath) { ArchiveHandle handle1, handle2; { ArchiveName name = GetSelf().GetArchiveName(oldPath); if (!name.IsValid()) { return nn::fs::ResultInvalidPathFormat(); } NN_UTIL_RETURN_IF_FAILED(GetSelf().GetArchiveHandle(&handle1, name)); } { ArchiveName name = GetSelf().GetArchiveName(newPath); if (!name.IsValid()) { return nn::fs::ResultInvalidPathFormat(); } NN_UTIL_RETURN_IF_FAILED(GetSelf().GetArchiveHandle(&handle2, name)); } if (handle1 != handle2) { return nn::fs::ResultUnsupportedOperation(); } { Accessor acc(GetSelf().GetHandleTable(), handle1); if (!acc) { // TODO: この Result でいい? return nn::fs::ResultArchiveNotFound(); } NN_UTIL_RETURN_IF_FAILED(acc->RenameFile(transaction, GetSelf().GetPathString(Move(oldPath)), GetSelf().GetPathString(Move(newPath)))); } return nn::ResultSuccess(); } Result RenameDirectory(nn::fs::Transaction transaction, Path oldPath, Path newPath) { ArchiveHandle handle1, handle2; { ArchiveName name = GetSelf().GetArchiveName(oldPath); if (!name.IsValid()) { return nn::fs::ResultInvalidPathFormat(); } NN_UTIL_RETURN_IF_FAILED(GetSelf().GetArchiveHandle(&handle1, name)); } { ArchiveName name = GetSelf().GetArchiveName(newPath); if (!name.IsValid()) { return nn::fs::ResultInvalidPathFormat(); } NN_UTIL_RETURN_IF_FAILED(GetSelf().GetArchiveHandle(&handle2, name)); } if (handle1 != handle2) { return nn::fs::ResultUnsupportedOperation(); } { Accessor acc(GetSelf().GetHandleTable(), handle1); if (!acc) { // TODO: この Result でいい? return nn::fs::ResultArchiveNotFound(); } NN_UTIL_RETURN_IF_FAILED(acc->RenameDirectory(transaction, GetSelf().GetPathString(Move(oldPath)), GetSelf().GetPathString(Move(newPath)))); } return nn::ResultSuccess(); } Result GetPathMark( nn::fs::PathMark* pathMark, Path path) { ArchiveName name = GetSelf().GetArchiveName(path); if (!name.IsValid()) { return nn::fs::ResultInvalidPathFormat(); } ArchiveHandle handle; NN_UTIL_RETURN_IF_FAILED(GetSelf().GetArchiveHandle(&handle, name)); { Accessor acc(GetSelf().GetHandleTable(), handle); if (!acc) { // TODO: この Result でいい? return nn::fs::ResultArchiveNotFound(); } NN_UTIL_RETURN_IF_FAILED(acc->GetPathMark( pathMark, GetSelf().GetPathString(Move(path)))); } return nn::ResultSuccess(); } }; }} #endif