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