1 /*---------------------------------------------------------------------------*
2   Project:  Horizon
3   File:     fs_FileBase.h
4 
5   Copyright (C)2009-2012 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: 46480 $
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             // For now, be sure to always Flush after Write
50             NN_TPANIC_IF_FALSE_(!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 
TrySetPriority(s32 priority)79     Result TrySetPriority(s32 priority) { return UserFileSystem::TrySetPriorityForFile(GetPtr(), priority); }
TryGetPriority(s32 * pOut)80     Result TryGetPriority(s32* pOut) const { return UserFileSystem::TryGetPriorityForFile(pOut, GetPtr()); }
81 
82 public:
83 
DuplicateHandle(Handle * pOut,s64 offset,s64 length)84     Result DuplicateHandle(Handle* pOut, s64 offset, s64 length)
85     {
86         return UserFileSystem::DuplicateHandleForFile(pOut, GetPtr(), offset, length);
87     }
88 
OpenDirect(Handle handle)89     void OpenDirect(Handle handle)
90     {
91         UserFileSystem::OpenDirect(&m_P, handle);
92     }
93 
CloseDirect()94     void CloseDirect()
95     {
96         if (GetPtr())
97         {
98             UserFileSystem::CloseDirect(GetPtr());
99             this->m_P = 0;
100         }
101     }
102 
GetHandle()103     Handle GetHandle()
104     {
105         return UserFileSystem::GetFileHandle(GetPtr());
106     }
107 
DetachHandle()108     void DetachHandle()
109     {
110         return UserFileSystem::DetachHandle(GetPtr());
111     }
112 
TryInitializeRaw(ArchiveHandle handle,const nn::fs::CTR::MPCore::Path & path,bit32 mode)113     Result TryInitializeRaw(ArchiveHandle handle, const nn::fs::CTR::MPCore::Path& path, bit32 mode)
114     {
115         return UserFileSystem::TryOpenFileRaw(&m_P, handle, path, mode);
116     }
117 
TryInitializeRawDirectly(bit32 archiveType,const nn::fs::CTR::MPCore::Path & archivePath,const nn::fs::CTR::MPCore::Path & path,bit32 mode)118     Result TryInitializeRawDirectly(bit32 archiveType, const nn::fs::CTR::MPCore::Path& archivePath, const nn::fs::CTR::MPCore::Path& path, bit32 mode)
119     {
120         return UserFileSystem::TryOpenFileRawDirectly(&m_P, archiveType, archivePath, path, mode);
121     }
122 
IsValid()123     bool IsValid() { return GetHandle().IsValid(); }
124 
125 private:
126 
127     // Because a value with 4-byte alignment is expected to be assigned, the lower 1 bit is used as a flag.
128     void* m_P;
129 
IsInitialized()130     bool IsInitialized() const { return GetPtr() != 0; }
131 
132     // Function for using the lower 1 bit of the address as a flag.
GetPtr()133     void*   GetPtr() const  { return reinterpret_cast<void*>(reinterpret_cast<uptr>(m_P) & ~static_cast<uptr>(0x1)); }
NeedFlush()134     void    NeedFlush()     { m_P = reinterpret_cast<void*>(reinterpret_cast<uptr>(m_P) | 0x1); }
DoneFlush()135     void    DoneFlush()     { m_P = reinterpret_cast<void*>(reinterpret_cast<uptr>(m_P) & ~static_cast<uptr>(0x1)); }
IsNotFlushed()136     bool    IsNotFlushed()  { return (reinterpret_cast<uptr>(m_P) & 0x1) != 0; }
137 };
138 
139 }}}
140 
141 #endif
142