1 /* Copyright (C) 2016 Wildfire Games. 2 * 3 * Permission is hereby granted, free of charge, to any person obtaining 4 * a copy of this software and associated documentation files (the 5 * "Software"), to deal in the Software without restriction, including 6 * without limitation the rights to use, copy, modify, merge, publish, 7 * distribute, sublicense, and/or sell copies of the Software, and to 8 * permit persons to whom the Software is furnished to do so, subject to 9 * the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included 12 * in all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 18 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 19 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 20 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 */ 22 23 /* 24 * 'tree' of VFS directories and files 25 */ 26 27 #ifndef INCLUDED_VFS_TREE 28 #define INCLUDED_VFS_TREE 29 30 #include <map> 31 32 #include "lib/file/file_system.h" // CFileInfo 33 #include "lib/file/common/file_loader.h" // PIFileLoader 34 #include "lib/file/common/real_directory.h" // PRealDirectory 35 #include "lib/file/vfs/vfs_path.h" 36 37 class VfsFile 38 { 39 public: 40 VfsFile(const VfsPath& name, size_t size, time_t mtime, size_t priority, const PIFileLoader& provider); 41 Name()42 const VfsPath& Name() const 43 { 44 return m_name; 45 } 46 Size()47 size_t Size() const 48 { 49 return m_size; 50 } 51 MTime()52 time_t MTime() const 53 { 54 return m_mtime; 55 } 56 Priority()57 size_t Priority() const 58 { 59 return m_priority; 60 } 61 Loader()62 const PIFileLoader& Loader() const 63 { 64 return m_loader; 65 } 66 67 private: 68 VfsPath m_name; 69 size_t m_size; 70 time_t m_mtime; 71 72 size_t m_priority; 73 74 PIFileLoader m_loader; 75 }; 76 77 78 class VfsDirectory 79 { 80 /** 81 * remove all files with a lower priority than @p file 82 * and do the same for all subdirectories recursively. 83 * @return true if the directory is empty afterwards 84 **/ 85 bool DeleteTree(const VfsFile& file); 86 87 public: 88 typedef std::map<VfsPath, VfsFile> VfsFiles; 89 typedef std::map<VfsPath, VfsDirectory> VfsSubdirectories; 90 91 VfsDirectory(); 92 93 /** 94 * remove the given file or subdirectory according to the priority of the 95 * passed .DELETED file. 96 * CAUTION: Invalidates all previously returned pointers of the file or 97 * subdirectory (and contents) if those have lower priority 98 * than @p file. 99 **/ 100 void DeleteSubtree(const VfsFile& file); 101 102 /** 103 * @return address of existing or newly inserted file. 104 **/ 105 VfsFile* AddFile(const VfsFile& file); 106 107 /** 108 * @return address of existing or newly inserted subdirectory. 109 **/ 110 VfsDirectory* AddSubdirectory(const VfsPath& name); 111 112 /** 113 * remove the given file from the virtual directory (no effect on 114 * the physical file). no effect if the file does not exist. 115 **/ 116 void RemoveFile(const VfsPath& name); 117 118 /** 119 * @return file with the given name. 120 * (note: non-const to allow changes to the file) 121 **/ 122 VfsFile* GetFile(const VfsPath& name); 123 124 /** 125 * @return subdirectory with the given name. 126 * (note: non-const to allow changes to the subdirectory) 127 **/ 128 VfsDirectory* GetSubdirectory(const VfsPath& name); 129 130 // note: exposing only iterators wouldn't enable callers to reserve space. 131 Files()132 const VfsFiles& Files() const 133 { 134 return m_files; 135 } 136 Subdirectories()137 const VfsSubdirectories& Subdirectories() const 138 { 139 return m_subdirectories; 140 } 141 142 /** 143 * side effect: the next ShouldPopulate() will return true. 144 **/ 145 void SetAssociatedDirectory(const PRealDirectory& realDirectory); 146 AssociatedDirectory()147 const PRealDirectory& AssociatedDirectory() const 148 { 149 return m_realDirectory; 150 } 151 152 /** 153 * @return whether this directory should be populated from its 154 * AssociatedDirectory(). note that calling this is a promise to 155 * do so if true is returned -- the flag is reset immediately. 156 **/ 157 bool ShouldPopulate(); 158 159 /** 160 * ensure the next ShouldPopulate returns true. 161 **/ 162 void RequestRepopulate(); 163 164 /** 165 * empty file and subdirectory lists (e.g. when rebuilding VFS). 166 * CAUTION: this invalidates all previously returned pointers. 167 **/ 168 void Clear(); 169 170 private: 171 VfsFiles m_files; 172 VfsSubdirectories m_subdirectories; 173 174 PRealDirectory m_realDirectory; 175 volatile intptr_t m_shouldPopulate; // (cpu_CAS can't be used on bool) 176 }; 177 178 179 /** 180 * @return a string containing file attributes (location, size, timestamp) and name. 181 **/ 182 extern std::wstring FileDescription(const VfsFile& file); 183 184 /** 185 * @return a string holding each files' description (one per line). 186 **/ 187 extern std::wstring FileDescriptions(const VfsDirectory& directory, size_t indentLevel); 188 189 /** 190 * append each directory's files' description to the given string. 191 **/ 192 void DirectoryDescriptionR(std::wstring& descriptions, const VfsDirectory& directory, size_t indentLevel); 193 194 #endif // #ifndef INCLUDED_VFS_TREE 195