1 /*---------------------------------------------------------------------------*
2   Project:  Horizon
3   File:     fs_FileBase.h
4 
5   Copyright (C)2009 Nintendo Co., Ltd.  All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law. They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12 
13   $Rev: 35053 $
14  *---------------------------------------------------------------------------*/
15 
16 #ifndef NN_FS_CTR_MPCORE_FS_FILEBASE_H_
17 #define NN_FS_CTR_MPCORE_FS_FILEBASE_H_
18 
19 #include <nn/Handle.h>
20 #include <nn/Result.h>
21 #include <nn/types.h>
22 #include <nn/assert.h>
23 #include <nn/util/util_Result.h>
24 #include <nn/os/os_HandleObject.h>
25 #include <nn/fs/fs_Parameters.h>
26 #include <nn/fs/fs_Result.h>
27 #include <nn/util/util_NonCopyable.h>
28 
29 #include <nn/fs/CTR/MPCore/fs_UserFileSystem.h>
30 
31 namespace nn { namespace fs { namespace detail {
32 
33 class FileBaseImpl : private nn::util::NonCopyable<FileBaseImpl>
34 {
35 protected:
36     typedef nn::fs::CTR::MPCore::detail::UserFileSystem UserFileSystem;
37 
FileBaseImpl()38     FileBaseImpl() : m_P(0) {}
39 
TryOpenImpl(const wchar_t * path,bit32 mode)40     Result TryOpenImpl(const wchar_t* path, bit32 mode)
41     {
42         return UserFileSystem::TryOpenFile(&m_P, path, mode);
43     }
44 
Finalize()45     void Finalize()
46     {
47         if (GetPtr())
48         {
49             // If you Write now, you must Flush
50             NN_TASSERT_(!IsNotFlushed());
51 
52             UserFileSystem::CloseFile(GetPtr());
53             this->m_P = 0;
54         }
55     }
~FileBaseImpl()56     ~FileBaseImpl() { Finalize(); }
57 
TryRead(s32 * pOut,s64 offset,void * buffer,size_t size)58     Result TryRead(s32* pOut, s64 offset, void* buffer, size_t size) { return UserFileSystem::TryReadFile(pOut, GetPtr(), offset, buffer, size); }
59     Result TryWrite(s32* pOut, s64 offset, const void* buffer, size_t size, bool flush=true)
60     {
61         if(!flush)
62         {
63             NeedFlush();
64         }
65         else
66         {
67             DoneFlush();
68         }
69         return UserFileSystem::TryWriteFile(pOut, GetPtr(), offset, buffer, size, flush);
70     }
TryGetSize(s64 * pOut)71     Result TryGetSize(s64* pOut) const { return UserFileSystem::TryGetFileSize(pOut, GetPtr()); }
TrySetSize(s64 size)72     Result TrySetSize(s64 size) { return UserFileSystem::TrySetFileSize(GetPtr(), size); }
TryFlush()73     Result TryFlush()
74     {
75         DoneFlush();
76         return UserFileSystem::TryFlush(GetPtr());
77     }
78 
79 public:
80 
DuplicateHandle(Handle * pOut,s64 offset,s64 length)81     Result DuplicateHandle(Handle* pOut, s64 offset, s64 length)
82     {
83         return UserFileSystem::DuplicateHandleForFile(pOut, GetPtr(), offset, length);
84     }
85 
OpenDirect(Handle handle)86     void OpenDirect(Handle handle)
87     {
88         UserFileSystem::OpenDirect(&m_P, handle);
89     }
90 
CloseDirect()91     void CloseDirect()
92     {
93         if (GetPtr())
94         {
95             UserFileSystem::CloseDirect(GetPtr());
96             this->m_P = 0;
97         }
98     }
99 
GetHandle()100     Handle GetHandle()
101     {
102         return UserFileSystem::GetFileHandle(GetPtr());
103     }
104 
DetachHandle()105     void DetachHandle()
106     {
107         return UserFileSystem::DetachHandle(GetPtr());
108     }
109 
TryInitializeRaw(ArchiveHandle handle,const nn::fs::CTR::MPCore::Path & path,bit32 mode)110     Result TryInitializeRaw(ArchiveHandle handle, const nn::fs::CTR::MPCore::Path& path, bit32 mode)
111     {
112         return UserFileSystem::TryOpenFileRaw(&m_P, handle, path, mode);
113     }
114 
TryInitializeRawDirectly(bit32 archiveType,const nn::fs::CTR::MPCore::Path & archivePath,const nn::fs::CTR::MPCore::Path & path,bit32 mode)115     Result TryInitializeRawDirectly(bit32 archiveType, const nn::fs::CTR::MPCore::Path& archivePath, const nn::fs::CTR::MPCore::Path& path, bit32 mode)
116     {
117         return UserFileSystem::TryOpenFileRawDirectly(&m_P, archiveType, archivePath, path, mode);
118     }
119 
IsValid()120     bool IsValid() { return GetHandle().IsValid(); }
121 
122 private:
123 
124     // A 4 byte alignment value should be entered, so use the lowest bit as a flag
125     void* m_P;
126 
IsInitialized()127     bool IsInitialized() const { return GetPtr() != 0; }
128 
129     // Function to use the lowest bit of the address as a flag
GetPtr()130     void*   GetPtr() const  { return reinterpret_cast<void*>(reinterpret_cast<uptr>(m_P) & ~static_cast<uptr>(0x1)); }
NeedFlush()131     void    NeedFlush()     { m_P = reinterpret_cast<void*>(reinterpret_cast<uptr>(m_P) | 0x1); }
DoneFlush()132     void    DoneFlush()     { m_P = reinterpret_cast<void*>(reinterpret_cast<uptr>(m_P) & ~static_cast<uptr>(0x1)); }
IsNotFlushed()133     bool    IsNotFlushed()  { return (reinterpret_cast<uptr>(m_P) & 0x1) != 0; }
134 };
135 
136 }}}
137 
138 #endif
139