1 /*---------------------------------------------------------------------------*
2   Project:  Horizon
3   File:     fslow_IArchive.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: 25433 $
14  *---------------------------------------------------------------------------*/
15 
16 #ifndef NN_FSLOW_FSLOW_ARCHIVEMAPFILESYSTEM_H_
17 #define NN_FSLOW_FSLOW_ARCHIVEMAPFILESYSTEM_H_
18 
19 #include <nn/Result.h>
20 #include <nn/fs/fs_Result.h>
21 #include <nn/util/util_Result.h>
22 
23 #pragma push
24 #pragma diag_suppress 2817
25 // #2817-D: temporary used for conditional class rvalue result (C++ core issue #446 resolution) 対策
26 #include <map>
27 #pragma pop
28 
29 #include "fslow_IArchive.h"
30 
31 namespace nn { namespace fslow {
32 
33 template <class Self, class TFileSystemTypeInfo, class TArchiveHandleTable, class ArchiveName>
34 class ArchiveMapFileSystem
35 {
36 public:
37     // スレッドセーフティ?
38 
39     typedef typename TFileSystemTypeInfo::Archive Archive;
40     typedef typename TFileSystemTypeInfo::File File;
41     typedef typename TFileSystemTypeInfo::Directory Directory;
42     typedef typename TFileSystemTypeInfo::FileHandle FileHandle;
43     typedef typename TFileSystemTypeInfo::DirectoryHandle DirectoryHandle;
44     typedef typename TFileSystemTypeInfo::Path Path;
45     typedef typename TFileSystemTypeInfo::DirectoryEntry DirectoryEntry;
46     typedef TArchiveHandleTable ArchiveHandleTable;
47     typedef typename ArchiveHandleTable::Handle ArchiveHandle;
48 
49     // Self に CRTP で要求するインターフェイス
50     //     ArchiveHandleTable& GetHandleTable();
51     //     Result RegisterToNameMap(ArchiveName, ArchiveHandle);
52     //     void UnregisterFromNameMap(ArchiveName);
53     //     ArchiveName GetArchiveName(Path);
54     //     Path GetPathString(Path);
55 
56 private:
57 
GetSelf()58     Self& GetSelf() { return static_cast<Self&>(*this); }
GetSelf()59     const Self& GetSelf() const { return static_cast<const Self&>(*this); }
60 
61     typedef typename ArchiveHandleTable::Accessor Accessor;
62 
63 public:
64 
AddArchive(const ArchiveName & name,Archive archive)65     Result AddArchive(const ArchiveName& name, Archive archive)
66     {
67         ArchiveHandle handle = GetSelf().GetHandleTable().Register(archive);
68         if (!handle)
69         {
70             // TODO: 適切な Result
71             return nn::fs::ResultOutOfMemory();
72         }
73         Result result = GetSelf().RegisterToNameMap(name, handle);
74         if (result.IsFailure())
75         {
76             GetSelf().GetHandleTable().Unregister(handle);
77         }
78         return result;
79     }
80 
RemoveArchive(const ArchiveName & name)81     Result RemoveArchive(const ArchiveName& name)
82     {
83         ArchiveHandle handle;
84         NN_UTIL_RETURN_IF_FAILED(GetSelf().GetArchiveHandle(&handle, name));
85         GetSelf().UnregisterFromNameMap(name);
86         GetSelf().GetHandleTable().Unregister(handle);
87         return nn::ResultSuccess();
88     }
89 
OpenFile(FileHandle * pOut,nn::fs::Transaction transaction,Path path,bit32 mode,nn::fs::Attributes attributes)90     Result OpenFile(FileHandle* pOut, nn::fs::Transaction transaction, Path path, bit32 mode, nn::fs::Attributes attributes)
91     {
92         nn::fs::PathMark pathMark;
93         pathMark.rawPathMark = 0;
94         return OpenFile( pOut, transaction, path, pathMark, mode, attributes);
95     }
96 
OpenFile(FileHandle * pOut,nn::fs::Transaction transaction,Path path,nn::fs::PathMark pathMark,bit32 mode,nn::fs::Attributes attributes)97     Result OpenFile(FileHandle* pOut, nn::fs::Transaction transaction, Path path, nn::fs::PathMark pathMark, bit32 mode, nn::fs::Attributes attributes)
98     {
99         ArchiveName name = GetSelf().GetArchiveName(path);
100         if (!name.IsValid())
101         {
102             return nn::fs::ResultInvalidPathFormat();
103         }
104         ArchiveHandle handle;
105         NN_UTIL_RETURN_IF_FAILED(GetSelf().GetArchiveHandle(&handle, name));
106         File file;
107         {
108             Accessor acc(GetSelf().GetHandleTable(), handle);
109             if (!acc)
110             {
111                 // TODO: この Result でいい?
112                 return nn::fs::ResultArchiveNotFound();
113             }
114             NN_UTIL_RETURN_IF_FAILED(acc->OpenFile(&file, transaction, GetSelf().GetPathString(Move(path)), pathMark, mode, attributes));
115         }
116         *pOut = FileHandle(handle, file);
117         return nn::ResultSuccess();
118     }
119 
ReadFile(s32 * pOut,const FileHandle & handle,s64 offset,void * buffer,size_t size)120     Result ReadFile(s32* pOut, const FileHandle& handle, s64 offset, void* buffer, size_t size)
121     {
122         Accessor acc(GetSelf().GetHandleTable(), handle.archiveHandle);
123         if (!acc)
124         {
125             // TODO: この Result でいい?
126             return nn::fs::ResultArchiveNotFound();
127         }
128         return handle.p->ReadBytes(pOut, offset, buffer, size);
129     }
130 
WriteFile(s32 * pOut,const FileHandle & handle,s64 offset,const void * buffer,size_t size)131     Result WriteFile(s32* pOut, const FileHandle& handle, s64 offset, const void* buffer, size_t size)
132     {
133         Accessor acc(GetSelf().GetHandleTable(), handle.archiveHandle);
134         if (!acc)
135         {
136             // TODO: この Result でいい?
137             return nn::fs::ResultArchiveNotFound();
138         }
139         return handle.p->WriteBytes(pOut, offset, buffer, size, true);
140     }
141 
GetFileSize(s64 * pOut,const FileHandle & handle)142     Result GetFileSize(s64* pOut, const FileHandle& handle)
143     {
144         Accessor acc(GetSelf().GetHandleTable(), handle.archiveHandle);
145         if (!acc)
146         {
147             // TODO: この Result でいい?
148             return nn::fs::ResultArchiveNotFound();
149         }
150         return handle.p->GetSize(pOut);
151     }
152 
SetFileSize(const FileHandle & handle,s64 size)153     Result SetFileSize(const FileHandle& handle, s64 size)
154     {
155         Accessor acc(GetSelf().GetHandleTable(), handle.archiveHandle);
156         if (!acc)
157         {
158             // TODO: この Result でいい?
159             return nn::fs::ResultArchiveNotFound();
160         }
161         return handle.p->SetSize(size);
162     }
163 
CloseFile(const FileHandle & handle)164     Result CloseFile(const FileHandle& handle)
165     {
166         Accessor acc(GetSelf().GetHandleTable(), handle.archiveHandle);
167         if (!acc)
168         {
169             // TODO: この Result でいい?
170             return nn::fs::ResultArchiveNotFound();
171         }
172         Result result = handle.p->Close();
173         acc->FreeFileObject(handle.p);
174         return result;
175     }
176 
OpenDirectory(DirectoryHandle * pOut,Path path)177     Result OpenDirectory(DirectoryHandle* pOut, Path path)
178     {
179         ArchiveName name = GetSelf().GetArchiveName(path);
180         if (!name.IsValid())
181         {
182             return nn::fs::ResultInvalidPathFormat();
183         }
184         ArchiveHandle handle;
185         NN_UTIL_RETURN_IF_FAILED(GetSelf().GetArchiveHandle(&handle, name));
186         Directory directory;
187         {
188             Accessor acc(GetSelf().GetHandleTable(), handle);
189             if (!acc)
190             {
191                 // TODO: この Result でいい?
192                 return nn::fs::ResultArchiveNotFound();
193             }
194             NN_UTIL_RETURN_IF_FAILED(acc->OpenDirectory(&directory, GetSelf().GetPathString(Move(path))));
195         }
196         *pOut = DirectoryHandle(handle, directory);
197         return nn::ResultSuccess();
198     }
199 
ReadDirectory(s32 * pNumEntriesOut,const DirectoryHandle & handle,DirectoryEntry entries[],s32 numEntries)200     Result ReadDirectory(s32* pNumEntriesOut, const DirectoryHandle& handle, DirectoryEntry entries[], s32 numEntries)
201     {
202         Accessor acc(GetSelf().GetHandleTable(), handle.archiveHandle);
203         if (!acc)
204         {
205             // TODO: この Result でいい?
206             return nn::fs::ResultArchiveNotFound();
207         }
208         return handle.p->Read(pNumEntriesOut, entries, numEntries);
209     }
210 
CloseDirectory(const DirectoryHandle & handle)211     Result CloseDirectory(const DirectoryHandle& handle)
212     {
213         Accessor acc(GetSelf().GetHandleTable(), handle.archiveHandle);
214         if (!acc)
215         {
216             // TODO: この Result でいい?
217             return nn::fs::ResultArchiveNotFound();
218         }
219         Result result = handle.p->Close();
220         acc->FreeDirectoryObject(handle.p);
221         return result;
222     }
223 
DeleteFile(nn::fs::Transaction transaction,Path path)224     Result DeleteFile(nn::fs::Transaction transaction, Path path)
225     {
226         ArchiveName name = GetSelf().GetArchiveName(path);
227         if (!name.IsValid())
228         {
229             return nn::fs::ResultInvalidPathFormat();
230         }
231         ArchiveHandle handle;
232         NN_UTIL_RETURN_IF_FAILED(GetSelf().GetArchiveHandle(&handle, name));
233         {
234             Accessor acc(GetSelf().GetHandleTable(), handle);
235             if (!acc)
236             {
237                 // TODO: この Result でいい?
238                 return nn::fs::ResultArchiveNotFound();
239             }
240             NN_UTIL_RETURN_IF_FAILED(acc->DeleteFile(transaction, GetSelf().GetPathString(Move(path))));
241         }
242         return nn::ResultSuccess();
243     }
244 
DeleteDirectory(nn::fs::Transaction transaction,Path path)245     Result DeleteDirectory(nn::fs::Transaction transaction, Path path)
246     {
247         ArchiveName name = GetSelf().GetArchiveName(path);
248         if (!name.IsValid())
249         {
250             return nn::fs::ResultInvalidPathFormat();
251         }
252         ArchiveHandle handle;
253         NN_UTIL_RETURN_IF_FAILED(GetSelf().GetArchiveHandle(&handle, name));
254         {
255             Accessor acc(GetSelf().GetHandleTable(), handle);
256             if (!acc)
257             {
258                 // TODO: この Result でいい?
259                 return nn::fs::ResultArchiveNotFound();
260             }
261             NN_UTIL_RETURN_IF_FAILED(acc->DeleteDirectory(transaction, GetSelf().GetPathString(Move(path))));
262         }
263         return nn::ResultSuccess();
264     }
265 
DeleteDirectoryRecursively(nn::fs::Transaction transaction,Path path)266     Result DeleteDirectoryRecursively(nn::fs::Transaction transaction, Path path)
267     {
268         ArchiveName name = GetSelf().GetArchiveName(path);
269         if (!name.IsValid())
270         {
271             return nn::fs::ResultInvalidPathFormat();
272         }
273         ArchiveHandle handle;
274         NN_UTIL_RETURN_IF_FAILED(GetSelf().GetArchiveHandle(&handle, name));
275         {
276             Accessor acc(GetSelf().GetHandleTable(), handle);
277             if (!acc)
278             {
279                 // TODO: この Result でいい?
280                 return nn::fs::ResultArchiveNotFound();
281             }
282             NN_UTIL_RETURN_IF_FAILED(acc->DeleteDirectoryRecursively(transaction, GetSelf().GetPathString(Move(path))));
283         }
284         return nn::ResultSuccess();
285     }
286 
CreateDirectory(nn::fs::Transaction transaction,Path path,nn::fs::Attributes attributes)287     Result CreateDirectory(nn::fs::Transaction transaction, Path path, nn::fs::Attributes attributes)
288     {
289         ArchiveName name = GetSelf().GetArchiveName(path);
290         if (!name.IsValid())
291         {
292             return nn::fs::ResultInvalidPathFormat();
293         }
294         ArchiveHandle handle;
295         NN_UTIL_RETURN_IF_FAILED(GetSelf().GetArchiveHandle(&handle, name));
296         {
297             Accessor acc(GetSelf().GetHandleTable(), handle);
298             if (!acc)
299             {
300                 // TODO: この Result でいい?
301                 return nn::fs::ResultArchiveNotFound();
302             }
303             NN_UTIL_RETURN_IF_FAILED(acc->CreateDirectory(transaction, GetSelf().GetPathString(Move(path)), attributes));
304         }
305         return nn::ResultSuccess();
306     }
307 
RenameFile(nn::fs::Transaction transaction,Path oldPath,Path newPath)308     Result RenameFile(nn::fs::Transaction transaction, Path oldPath, Path newPath)
309     {
310         ArchiveHandle handle1, handle2;
311         {
312             ArchiveName name = GetSelf().GetArchiveName(oldPath);
313             if (!name.IsValid())
314             {
315                 return nn::fs::ResultInvalidPathFormat();
316             }
317             NN_UTIL_RETURN_IF_FAILED(GetSelf().GetArchiveHandle(&handle1, name));
318         }
319         {
320             ArchiveName name = GetSelf().GetArchiveName(newPath);
321             if (!name.IsValid())
322             {
323                 return nn::fs::ResultInvalidPathFormat();
324             }
325             NN_UTIL_RETURN_IF_FAILED(GetSelf().GetArchiveHandle(&handle2, name));
326         }
327         if (handle1 != handle2)
328         {
329             return nn::fs::ResultUnsupportedOperation();
330         }
331         {
332             Accessor acc(GetSelf().GetHandleTable(), handle1);
333             if (!acc)
334             {
335                 // TODO: この Result でいい?
336                 return nn::fs::ResultArchiveNotFound();
337             }
338             NN_UTIL_RETURN_IF_FAILED(acc->RenameFile(transaction, GetSelf().GetPathString(Move(oldPath)), GetSelf().GetPathString(Move(newPath))));
339         }
340         return nn::ResultSuccess();
341     }
342 
RenameDirectory(nn::fs::Transaction transaction,Path oldPath,Path newPath)343     Result RenameDirectory(nn::fs::Transaction transaction, Path oldPath, Path newPath)
344     {
345         ArchiveHandle handle1, handle2;
346         {
347             ArchiveName name = GetSelf().GetArchiveName(oldPath);
348             if (!name.IsValid())
349             {
350                 return nn::fs::ResultInvalidPathFormat();
351             }
352             NN_UTIL_RETURN_IF_FAILED(GetSelf().GetArchiveHandle(&handle1, name));
353         }
354         {
355             ArchiveName name = GetSelf().GetArchiveName(newPath);
356             if (!name.IsValid())
357             {
358                 return nn::fs::ResultInvalidPathFormat();
359             }
360             NN_UTIL_RETURN_IF_FAILED(GetSelf().GetArchiveHandle(&handle2, name));
361         }
362         if (handle1 != handle2)
363         {
364             return nn::fs::ResultUnsupportedOperation();
365         }
366         {
367             Accessor acc(GetSelf().GetHandleTable(), handle1);
368             if (!acc)
369             {
370                 // TODO: この Result でいい?
371                 return nn::fs::ResultArchiveNotFound();
372             }
373             NN_UTIL_RETURN_IF_FAILED(acc->RenameDirectory(transaction, GetSelf().GetPathString(Move(oldPath)), GetSelf().GetPathString(Move(newPath))));
374         }
375         return nn::ResultSuccess();
376     }
377 
GetPathMark(nn::fs::PathMark * pathMark,Path path)378     Result GetPathMark( nn::fs::PathMark* pathMark, Path path)
379     {
380         ArchiveName name = GetSelf().GetArchiveName(path);
381         if (!name.IsValid())
382         {
383             return nn::fs::ResultInvalidPathFormat();
384         }
385         ArchiveHandle handle;
386         NN_UTIL_RETURN_IF_FAILED(GetSelf().GetArchiveHandle(&handle, name));
387         {
388             Accessor acc(GetSelf().GetHandleTable(), handle);
389             if (!acc)
390             {
391                 // TODO: この Result でいい?
392                 return nn::fs::ResultArchiveNotFound();
393             }
394             NN_UTIL_RETURN_IF_FAILED(acc->GetPathMark( pathMark, GetSelf().GetPathString(Move(path))));
395         }
396         return nn::ResultSuccess();
397     }
398 
399 };
400 
401 }}
402 
403 #endif
404