dl
dl_tool_archiver.h
浏览该文件的文档.
1
12#pragma once
13
14#include <memory/dl_buffer.h>
17#include <io/dl_file.h>
18#include <memory/dl_crypto.h>
19#include <base/dl_string.h>
20
21
22namespace dl::Tool
23{
24 constexpr uint16_t ARCHIVER_TYPE = 0x4002;
25 constexpr uint8_t ARCHIVER_VERSION = 1;
26
29{
30public:
31 struct Head
32 {
33 uint16_t _type;
34 uint8_t _version;
36 uint32_t _sizeFileList; // 文件列表(压缩前大小)
37 uint32_t _sizeFileListCompress; // 文件列表(压缩后大小)
38 uint64_t _sizeFileBlock; // 文件块大小(压缩前)
39 };
40 struct FileInfo
41 {
42 uint64_t _offset; // 内存偏移
43 uint32_t _size; // 大小
44 uint32_t _crc; // crc
45 };
46 using FileList = std::unordered_map<std::string, FileInfo>;
47
48 struct Param
49 {
50 std::string _src;
51 std::string _out;
53 bool _bCrc;
54 };
55
56 static void Compress(const Param& p)
57 {
58 std::vector<std::string> vec_file;
59 File::GetPathFileAll(p._src, vec_file);
60 if (vec_file.empty())
61 {
62 log_warn("文件数量为0!");
63 }
64 FileList all_file;
65 // 文件块
67 for (auto& iter : vec_file)
68 {
69 Buffer buf = File::GetBuffer(iter);
70 uint32_t crc = 0;
71 if (p._bCrc)
72 crc = Crypto::HashCrc32(buf);
73
74 FileInfo& f = all_file[File::GetRelative(iter, p._src)];
75 f._offset = s.GetPos();
76 f._size = (uint32_t)buf.size();
77 f._crc = crc;
78
79 uint64_t size_file = (uint64_t)buf.size();
80 s.Write(&size_file);
81 s.Write(&buf);
82 }
83 // 文件列表
84 StreamOutput s1;
85 s1.Write(&all_file);
86
87 // 头
88 Head head;
89 head._type = ARCHIVER_TYPE;
92 head._sizeFileList = (uint32_t)s1.GetPos();
94 head._sizeFileListCompress = (uint32_t)s1.GetPos();
95 head._sizeFileBlock = s.GetPos();
96
98
99 StreamOutput s_all;
100 s_all.Write(&head);
101 s_all.Write(s1.GetData(), s1.GetPos());
102 s_all.Write(s.GetData(), s.GetPos());
103
104 s_all.Save(p._out);
105 }
106 static bool Decompress(BufferView buf, std::string_view out)
107 {
108 StreamInput s_all;
109 s_all.LoadFromMemory(buf);
110
111 Head head;
112 s_all.Read(&head);
113
114 if (head._type != ARCHIVER_TYPE)
115 {
116 log_err("文件类型错误!");
117 return false;
118 }
119 if (head._version != ARCHIVER_VERSION)
120 {
121 log_err("存档版本错误!");
122 return false;
123 }
124 // 文件列表
125 FileList all_file;
126 {
127 Buffer buf_temp;
128 BufferView buf;
129 if (head._modeCompress == Memory::E_LZ4)
130 {
131 buf_temp = Memory::DecompressLz4(
132 { s_all.GetCurrent(), head._sizeFileListCompress }, (size_t)head._sizeFileList);
133 buf = buf_temp;
134 }
135#ifndef DL_DISABLE_ZLIB
136 else if (head._modeCompress == Memory::E_ZIP)
137 {
138 buf_temp = Memory::DecompressZip(
139 { s_all.GetCurrent(), head._sizeFileListCompress }, (size_t)head._sizeFileList);
140 buf = buf_temp;
141 }
142#endif
143 else
144 buf = { s_all.GetCurrent(), head._sizeFileListCompress };
145 StreamInput s1;
146 s1.LoadFromMemory(buf);
147 s1.Read(&all_file);
148
149 // 偏移
150 s_all.SetPos(s_all.GetPos() + head._sizeFileListCompress);
151 }
152 // 文件块
153 {
154 Buffer buf_temp;
155 BufferView buf;
156 if (head._modeCompress == Memory::E_LZ4)
157 {
158 buf_temp = Memory::DecompressLz4(
159 { s_all.GetCurrent(), s_all.GetRemain() }, (size_t)head._sizeFileBlock);
160 buf = buf_temp;
161 }
162#ifndef DL_DISABLE_ZLIB
163 else if (head._modeCompress == Memory::E_ZIP)
164 {
165 buf_temp = Memory::DecompressZip(
166 { s_all.GetCurrent(), s_all.GetRemain() }, (size_t)head._sizeFileBlock);
167 buf = buf_temp;
168 }
169#endif
170 else
171 buf = { s_all.GetCurrent(), s_all.GetRemain() };
172
173 size_t count = 0;
174 for (auto& [name, info] : all_file)
175 {
176 std::byte* p = buf.data() + info._offset;
177 std::size_t size_file = (std::size_t)*(uint64_t*)p;
178 if (info._size != size_file)
179 {
180 log_err("文件大小不匹配:{}", size_file);
181 continue;
182 }
183 p += sizeof(uint64_t);
184
185 std::string path_name = out + name;
186 if (!File::CreateFolder(File::GetFilePath(path_name)))
187 {
188 log_err("路径创建失败:{}", File::GetFilePath(path_name));
189 continue;
190 }
191 if (!File::SaveBuffer(
192 { p, size_file }, path_name))
193 {
194 log_err("文件保存失败:{}", path_name);
195 continue;
196 }
197 ++count;
198 }
199 return count == all_file.size();
200 }
201 }
202 static bool Decompress(std::string_view src, std::string_view out)
203 {
204 Buffer buf = File::GetBuffer(src);
205 if (buf.empty())
206 {
207 log_err("加载文件失败:{}", src);
208 return false;
209 }
210 return Decompress(buf, out);
211 }
212 static bool GetFileList(BufferView buf, FileList& all_file)
213 {
214 StreamInput s_all;
215 s_all.LoadFromMemory(buf);
216
217 Head head;
218 s_all.Read(&head);
219
220 if (head._type != ARCHIVER_TYPE)
221 {
222 log_err("文件类型错误!");
223 return false;
224 }
225 if (head._version != ARCHIVER_VERSION)
226 {
227 log_err("存档版本错误!");
228 return false;
229 }
230 {
231 Buffer buf_temp;
232 BufferView buf;
233 if (head._modeCompress == Memory::E_LZ4)
234 {
235 buf_temp = Memory::DecompressLz4(
236 { s_all.GetCurrent(), head._sizeFileListCompress }, (size_t)head._sizeFileList);
237 buf = buf_temp;
238 }
239#ifndef DL_DISABLE_ZLIB
240 else if (head._modeCompress == Memory::E_ZIP)
241 {
242 buf_temp = Memory::DecompressZip(
243 { s_all.GetCurrent(), head._sizeFileListCompress }, (size_t)head._sizeFileList);
244 buf = buf_temp;
245 }
246#endif
247 else
248 buf = { s_all.GetCurrent(), head._sizeFileListCompress };
249 StreamInput s1;
250 s1.LoadFromMemory(buf);
251 s1.Read(&all_file);
252 }
253 return true;
254 }
255private:
256 // 头
257
258 // 文件列表(压缩)
259 // name、FileInfo
260
261 // 文件数据(压缩)
262 // buffer
263};
264
265}
size_t size() const
size_t size() const
std::byte * data()
二进制输入流
void LoadFromMemory(BufferView buf, bool decompress=false)
void SetPos(size_t pos)
二进制输出流
void Compress(Memory::CompressMode mode)
压缩当前内存
bool Save(std::string_view path_name, bool compress=false)
保存到文件
const std::byte * GetData()
返回指向的内存指针
size_t GetPos()
返回 流位置
void Write(const T *data)
写入一个对象
文件夹打包解包器
std::unordered_map< std::string, FileInfo > FileList
static void Compress(const Param &p)
static bool GetFileList(BufferView buf, FileList &all_file)
static bool Decompress(BufferView buf, std::string_view out)
static bool Decompress(std::string_view src, std::string_view out)
表示一段内存
密码算法
文件系统
#define log_warn(...)
#define log_err(...)
字符串相关
uint32_t HashCrc32(BufferView buf, uint32_t crc=0)
crc32哈希
void GetPathFileAll(std::string_view path, std::vector< std::string > &ret, std::string_view regex="", bool recursion=true)
获取文件夹所有文件
bool SaveBuffer(BufferView buf, std::string_view path_name)
将内存保存为文件
std::string GetFilePath(std::string_view path_name)
返回文件所在路径
bool CreateFolder(std::string_view path)
创建目录
std::string GetRelative(std::string_view path_name, std::string_view path_base)
返回相对路径
Buffer GetBuffer(std::string_view path_name)
返回文件内存
Buffer DecompressLz4(BufferView src, size_t size_origin=0)
解压缩数据,使用lz4算法
Buffer DecompressZip(BufferView src, size_t size_origin=0)
解压缩数据,使用libz
constexpr uint16_t ARCHIVER_TYPE
constexpr uint8_t ARCHIVER_VERSION
Memory::CompressMode _compressMode