-
Notifications
You must be signed in to change notification settings - Fork 9
/
archive.h
270 lines (236 loc) · 8.22 KB
/
archive.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
267
268
269
270
/*
Mod Organizer archive handling
Copyright (C) 2012 Sebastian Herbord, 2020 MO2 Team. All rights reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef ARCHIVE_H
#define ARCHIVE_H
#include <cstdint>
#include <functional>
#include <memory>
#include <string>
#ifndef DLLEXPORT
#ifdef MODORGANIZER_ARCHIVE_BUILDING
#define DLLEXPORT _declspec(dllexport)
#else
#define DLLEXPORT _declspec(dllimport)
#endif
#endif
class FileData
{
public:
/**
* @return the path of this entry in the archive (usually relative, unless the archive
* contains absolute path).
*/
virtual std::wstring getArchiveFilePath() const = 0;
/**
* @return the size of this entry in bytes (uncompressed).
*/
virtual uint64_t getSize() const = 0;
/**
* @brief Add the given filepath to the list of files to create from this
* entry when extracting.
*
* @param filepath The filepath to add, relative to the output folder.
*/
virtual void addOutputFilePath(std::wstring const& filepath) = 0;
/**
* @brief Retrieve the list of filepaths to extract this entry to.
*
* @return the list of paths this entry should be extracted to, relative to the
* output folder.
*/
virtual const std::vector<std::wstring>& getOutputFilePaths() const = 0;
/**
* @brief Clear the list of output file paths for this entry.
*/
virtual void clearOutputFilePaths() = 0;
/**
* @return the CRC of this file.
*/
virtual uint64_t getCRC() const = 0;
/**
* @return true if this entry is a directory, false otherwize.
*/
virtual bool isDirectory() const = 0;
};
class Archive
{
public: // Declarations
enum class LogLevel
{
Debug,
Info,
Warning,
Error
};
enum class ProgressType
{
// Indicates the 7z progression in the archive (related to reading the archive. When
// extracting
// a lot of files, this may reach 100% way before the extraction is complete since
// most of the
// time will be spend writing data and not reading it (use EXTRACTION in this case).
// When
// extracting few small files, this may be useful for solid archives since most of
// the time
// will be spent in reading and decompressing the archive rather than in writing the
// actual files.
ARCHIVE,
// Progress about extraction. If this reach 100%, it means that the extraction of
// all files is
// complete. The EXTRACTION progress may not start immediately, and might be kind of
// chaotic when
// extracting few files from an archive, but is much more representative of the
// actual progress
// than ARCHIVE.
EXTRACTION
};
enum class FileChangeType
{
EXTRACTION_START,
EXTRACTION_END
};
static constexpr int MAX_PASSWORD_LENGTH = 256;
/**
* List of callbacks:
*/
using LogCallback = std::function<void(LogLevel, std::wstring const& log)>;
using ProgressCallback = std::function<void(ProgressType, uint64_t, uint64_t)>;
using PasswordCallback = std::function<std::wstring()>;
using FileChangeCallback = std::function<void(FileChangeType, std::wstring const&)>;
using ErrorCallback = std::function<void(std::wstring const&)>;
/**
*
*/
enum class Error
{
ERROR_NONE,
ERROR_EXTRACT_CANCELLED,
ERROR_LIBRARY_NOT_FOUND,
ERROR_LIBRARY_INVALID,
ERROR_ARCHIVE_NOT_FOUND,
ERROR_FAILED_TO_OPEN_ARCHIVE,
ERROR_INVALID_ARCHIVE_FORMAT,
ERROR_LIBRARY_ERROR,
ERROR_ARCHIVE_INVALID,
ERROR_OUT_OF_MEMORY
};
public: // Special member functions:
virtual ~Archive() {}
public:
/**
* @brief Check if this Archive wrapper is in a valid state.
*
* A non-valid Archive instance usually means that the 7z DLLs could not be loaded
* properly. Failures to open or extract archives do not invalidate the Archive, so
* this should only be used to check if the Archive object has been initialized
* properly.
*
* @return true if this instance is valid, false otherwise.
*/
virtual bool isValid() const = 0;
/**
* @return retrieve the error-code of the last error that occurred.
*/
virtual Error getLastError() const = 0;
/**
* @brief Set the callback used to log messages.
*
* To remove the callback, you can pass a default-constructed LogCallback object.
*
* @param logCallback The new callback to use for logging message.
*/
virtual void setLogCallback(LogCallback logCallback) = 0;
/**
* @brief Open the given archive.
*
* @param archivePath Path to the archive to open.
* @param passwordCallback Callback to use to ask user for password. This callback
* must remain valid until extraction is complete since some types of archives only
* requires password when extracting.
*
* @return true if the archive was open properly, false otherwise.
*/
virtual bool open(std::wstring const& archivePath,
PasswordCallback passwordCallback) = 0;
/**
* @brief Close the currently opened archive.
*/
virtual void close() = 0;
/**
* @return the list of files in the currently opened archive.
*/
virtual const std::vector<FileData*>& getFileList() const = 0;
/**
* @brief Extract the content of the archive.
*
* This function uses the filenames from FileData to obtain the extraction paths of
* file. All the callbacks are optional (you can specify default-constructed
* std::function). Overloads with one or two callbacks are also provided.
*
* @param outputDirectory Path to the directory where the archive should be extracted.
* If not empty, conflicting files will be replaced by the extracted ones.
* @param progressCallback Function called to notify extraction progress.
* @param fileChangeCallback Function called when the file currently being extracted
* changes.
* @param errorCallback Function called when an error occurs.
*
* @return true if the archive was extracted, false otherwise.
*/
virtual bool extract(std::wstring const& outputDirectory,
ProgressCallback progressCallback,
FileChangeCallback fileChangeCallback,
ErrorCallback errorCallback) = 0;
/**
* @brief Cancel the current extraction process.
*/
virtual void cancel() = 0;
// A bunch of useful overloads (with one or two callbacks):
bool extract(std::wstring const& outputDirectory, ErrorCallback errorCallback)
{
return extract(outputDirectory, {}, {}, errorCallback);
}
bool extract(std::wstring const& outputDirectory, ProgressCallback progressCallback)
{
return extract(outputDirectory, progressCallback, {}, {});
}
bool extract(std::wstring const& outputDirectory,
FileChangeCallback fileChangeCallback)
{
return extract(outputDirectory, {}, fileChangeCallback, {});
}
bool extract(std::wstring const& outputDirectory, ProgressCallback progressCallback,
ErrorCallback errorCallback)
{
return extract(outputDirectory, progressCallback, {}, errorCallback);
}
bool extract(std::wstring const& outputDirectory, ProgressCallback progressCallback,
FileChangeCallback fileChangeCallback)
{
return extract(outputDirectory, progressCallback, fileChangeCallback, {});
}
bool extract(std::wstring const& outputDirectory,
FileChangeCallback fileChangeCallback, ErrorCallback errorCallback)
{
return extract(outputDirectory, {}, fileChangeCallback, errorCallback);
}
};
/**
* @brief Factory function for archive-objects.
*
* @return a pointer to a new Archive object that can be used to manipulate archives.
*/
DLLEXPORT std::unique_ptr<Archive> CreateArchive();
#endif // ARCHIVE_H