FileList.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. /*
  2. * Copyright (c) 2014, Oculus VR, Inc.
  3. * All rights reserved.
  4. *
  5. * This source code is licensed under the BSD-style license found in the
  6. * LICENSE file in the root directory of this source tree. An additional grant
  7. * of patent rights can be found in the PATENTS file in the same directory.
  8. *
  9. */
  10. /// \file FileList.h
  11. ///
  12. #include "NativeFeatureIncludes.h"
  13. #if _RAKNET_SUPPORT_FileOperations==1
  14. #ifndef __FILE_LIST
  15. #define __FILE_LIST
  16. #include "Export.h"
  17. #include "DS_List.h"
  18. #include "RakMemoryOverride.h"
  19. #include "RakNetTypes.h"
  20. #include "FileListNodeContext.h"
  21. #include "RakString.h"
  22. #ifdef _MSC_VER
  23. #pragma warning( push )
  24. #endif
  25. namespace RakNet
  26. {
  27. class BitStream;
  28. }
  29. namespace RakNet
  30. {
  31. /// Forward declarations
  32. class RakPeerInterface;
  33. class FileList;
  34. /// Represents once instance of a file
  35. struct FileListNode
  36. {
  37. /// Name of the file
  38. RakNet::RakString filename;
  39. /// Full path to the file, which may be different than filename
  40. RakNet::RakString fullPathToFile;
  41. /// File data (may be null if not ready)
  42. char *data;
  43. /// Length of \a data. May be greater than fileLength if prepended with a file hash
  44. BitSize_t dataLengthBytes;
  45. /// Length of the file
  46. unsigned fileLengthBytes;
  47. /// User specific data for whatever, describing this file.
  48. FileListNodeContext context;
  49. /// If true, data and dataLengthBytes should be empty. This is just storing the filename
  50. bool isAReference;
  51. };
  52. /// Callback interface set with FileList::SetCallback() in case you want progress notifications when FileList::AddFilesFromDirectory() is called
  53. class RAK_DLL_EXPORT FileListProgress
  54. {
  55. public:
  56. // GetInstance() and DestroyInstance(instance*)
  57. STATIC_FACTORY_DECLARATIONS(FileListProgress)
  58. FileListProgress() {}
  59. virtual ~FileListProgress() {}
  60. /// First callback called when FileList::AddFilesFromDirectory() starts
  61. virtual void OnAddFilesFromDirectoryStarted(FileList *fileList, char *dir) {
  62. (void) fileList;
  63. (void) dir;
  64. }
  65. /// Called for each directory, when that directory begins processing
  66. virtual void OnDirectory(FileList *fileList, char *dir, unsigned int directoriesRemaining) {
  67. (void) fileList;
  68. (void) dir;
  69. (void) directoriesRemaining;
  70. }
  71. /// Called for each file, when that file begins processing
  72. virtual void OnFile(FileList *fileList, char *dir, char *fileName, unsigned int fileSize) {
  73. (void) fileList;
  74. (void) dir;
  75. (void) fileName;
  76. (void) fileSize;
  77. }
  78. /// \brief This function is called when we are sending a file to a remote system.
  79. /// \param[in] fileName The name of the file being sent
  80. /// \param[in] fileLengthBytes How long the file is
  81. /// \param[in] offset The offset in bytes into the file that we are sending
  82. /// \param[in] bytesBeingSent How many bytes we are sending this push
  83. /// \param[in] done If this file is now done with this push
  84. /// \param[in] targetSystem Who we are sending to
  85. virtual void OnFilePush(const char *fileName, unsigned int fileLengthBytes, unsigned int offset, unsigned int bytesBeingSent, bool done, SystemAddress targetSystem, unsigned short setId)
  86. {
  87. (void) fileName;
  88. (void) fileLengthBytes;
  89. (void) offset;
  90. (void) bytesBeingSent;
  91. (void) done;
  92. (void) targetSystem;
  93. (void) setId;
  94. }
  95. /// \brief This function is called when all files have been read and are being transferred to a remote system
  96. virtual void OnFilePushesComplete( SystemAddress systemAddress, unsigned short setId )
  97. {
  98. (void) systemAddress;
  99. (void) setId;
  100. }
  101. /// \brief This function is called when a send to a system was aborted (probably due to disconnection)
  102. virtual void OnSendAborted( SystemAddress systemAddress )
  103. {
  104. (void) systemAddress;
  105. }
  106. };
  107. /// Implementation of FileListProgress to use RAKNET_DEBUG_PRINTF
  108. class RAK_DLL_EXPORT FLP_Printf : public FileListProgress
  109. {
  110. public:
  111. // GetInstance() and DestroyInstance(instance*)
  112. STATIC_FACTORY_DECLARATIONS(FLP_Printf)
  113. FLP_Printf() {}
  114. virtual ~FLP_Printf() {}
  115. /// First callback called when FileList::AddFilesFromDirectory() starts
  116. virtual void OnAddFilesFromDirectoryStarted(FileList *fileList, char *dir);
  117. /// Called for each directory, when that directory begins processing
  118. virtual void OnDirectory(FileList *fileList, char *dir, unsigned int directoriesRemaining);
  119. /// \brief This function is called when all files have been transferred to a particular remote system
  120. virtual void OnFilePushesComplete( SystemAddress systemAddress, unsigned short setID );
  121. /// \brief This function is called when a send to a system was aborted (probably due to disconnection)
  122. virtual void OnSendAborted( SystemAddress systemAddress );
  123. };
  124. class RAK_DLL_EXPORT FileList
  125. {
  126. public:
  127. // GetInstance() and DestroyInstance(instance*)
  128. STATIC_FACTORY_DECLARATIONS(FileList)
  129. FileList();
  130. ~FileList();
  131. /// \brief Add all the files at a given directory.
  132. /// \param[in] applicationDirectory The first part of the path. This is not stored as part of the filename. Use \ as the path delineator.
  133. /// \param[in] subDirectory The rest of the path to the file. This is stored as a prefix to the filename
  134. /// \param[in] writeHash The first 4 bytes is a hash of the file, with the remainder the actual file data (should \a writeData be true)
  135. /// \param[in] writeData Write the contents of each file
  136. /// \param[in] recursive Whether or not to visit subdirectories
  137. /// \param[in] context User defined byte to store with each file. Use for whatever you want.
  138. void AddFilesFromDirectory(const char *applicationDirectory, const char *subDirectory, bool writeHash, bool writeData, bool recursive, FileListNodeContext context);
  139. /// Deallocate all memory
  140. void Clear(void);
  141. /// Write all encoded data into a bitstream
  142. void Serialize(RakNet::BitStream *outBitStream);
  143. /// Read all encoded data from a bitstream. Clear() is called before deserializing.
  144. bool Deserialize(RakNet::BitStream *inBitStream);
  145. /// \brief Given the existing set of files, search applicationDirectory for the same files.
  146. /// \details For each file that is missing or different, add that file to \a missingOrChangedFiles. Note: the file contents are not written, and only the hash if written if \a alwaysWriteHash is true
  147. /// alwaysWriteHash and neverWriteHash are optimizations to avoid reading the file contents to generate the hash if not necessary because the file is missing or has different lengths anyway.
  148. /// \param[in] applicationDirectory The first part of the path. This is not stored as part of the filename. Use \ as the path delineator.
  149. /// \param[out] missingOrChangedFiles Output list written to
  150. /// \param[in] alwaysWriteHash If true, and neverWriteHash is false, will hash the file content of the file on disk, and write that as the file data with a length of SHA1_LENGTH bytes. If false, if the file length is different, will only write the filename.
  151. /// \param[in] neverWriteHash If true, will never write the hash, even if available. If false, will write the hash if the file lengths are the same and it was forced to do a comparison.
  152. void ListMissingOrChangedFiles(const char *applicationDirectory, FileList *missingOrChangedFiles, bool alwaysWriteHash, bool neverWriteHash);
  153. /// \brief Return the files that need to be written to make \a input match this current FileList.
  154. /// \details Specify dirSubset to only consider files that start with this path
  155. /// specify remoteSubdir to assume that all filenames in input start with this path, so strip it off when comparing filenames.
  156. /// \param[in] input Full list of files
  157. /// \param[out] output Files that we need to match input
  158. /// \param[in] dirSubset If the filename does not start with this path, just skip this file.
  159. /// \param[in] remoteSubdir Remove this from the filenames of \a input when comparing to existing filenames.
  160. void GetDeltaToCurrent(FileList *input, FileList *output, const char *dirSubset, const char *remoteSubdir);
  161. /// \brief Assuming FileList contains a list of filenames presumably without data, read the data for these filenames
  162. /// \param[in] applicationDirectory Prepend this path to each filename. Trailing slash will be added if necessary. Use \ as the path delineator.
  163. /// \param[in] writeFileData True to read and store the file data. The first SHA1_LENGTH bytes will contain the hash if \a writeFileHash is true
  164. /// \param[in] writeFileHash True to read and store the hash of the file data. The first SHA1_LENGTH bytes will contain the hash if \a writeFileHash is true
  165. /// \param[in] removeUnknownFiles If a file does not exist on disk but is in the file list, remove it from the file list?
  166. void PopulateDataFromDisk(const char *applicationDirectory, bool writeFileData, bool writeFileHash, bool removeUnknownFiles);
  167. /// By default, GetDeltaToCurrent tags files as non-references, meaning they are assumed to be populated later
  168. /// This tags all files as references, required for IncrementalReadInterface to process them incrementally
  169. void FlagFilesAsReferences(void);
  170. /// \brief Write all files to disk, prefixing the paths with applicationDirectory
  171. /// \param[in] applicationDirectory path prefix
  172. void WriteDataToDisk(const char *applicationDirectory);
  173. /// \brief Add a file, given data already in memory.
  174. /// \param[in] filename Name of a file, optionally prefixed with a partial or complete path. Use \ as the path delineator.
  175. /// \param[in] fullPathToFile Full path to the file on disk
  176. /// \param[in] data Contents to write
  177. /// \param[in] dataLength length of the data, which may be greater than fileLength should you prefix extra data, such as the hash
  178. /// \param[in] fileLength Length of the file
  179. /// \param[in] context User defined byte to store with each file. Use for whatever you want.
  180. /// \param[in] isAReference Means that this is just a reference to a file elsewhere - does not actually have any data
  181. /// \param[in] takeDataPointer If true, do not allocate dataLength. Just take the pointer passed to the \a data parameter
  182. void AddFile(const char *filename, const char *fullPathToFile, const char *data, const unsigned dataLength, const unsigned fileLength, FileListNodeContext context, bool isAReference=false, bool takeDataPointer=false);
  183. /// \brief Add a file, reading it from disk.
  184. /// \param[in] filepath Complete path to the file, including the filename itself
  185. /// \param[in] filename filename to store internally, anything you want, but usually either the complete path or a subset of the complete path.
  186. /// \param[in] context User defined byte to store with each file. Use for whatever you want.
  187. void AddFile(const char *filepath, const char *filename, FileListNodeContext context);
  188. /// \brief Delete all files stored in the file list.
  189. /// \param[in] applicationDirectory Prefixed to the path to each filename. Use \ as the path delineator.
  190. void DeleteFiles(const char *applicationDirectory);
  191. /// \brief Adds a callback to get progress reports about what the file list instances do.
  192. /// \param[in] cb A pointer to an externally defined instance of FileListProgress. This pointer is held internally, so should remain valid as long as this class is valid.
  193. void AddCallback(FileListProgress *cb);
  194. /// \brief Removes a callback
  195. /// \param[in] cb A pointer to an externally defined instance of FileListProgress that was previously added with AddCallback()
  196. void RemoveCallback(FileListProgress *cb);
  197. /// \brief Removes all callbacks
  198. void ClearCallbacks(void);
  199. /// Returns all callbacks added with AddCallback()
  200. /// \param[out] callbacks The list is set to the list of callbacks
  201. void GetCallbacks(DataStructures::List<FileListProgress*> &callbacks);
  202. // Here so you can read it, but don't modify it
  203. DataStructures::List<FileListNode> fileList;
  204. static bool FixEndingSlash(char *str);
  205. protected:
  206. DataStructures::List<FileListProgress*> fileListProgressCallbacks;
  207. };
  208. } // namespace RakNet
  209. #ifdef _MSC_VER
  210. #pragma warning( pop )
  211. #endif
  212. #endif
  213. #endif // _RAKNET_SUPPORT_FileOperations
粤ICP备19079148号