rlm@1
|
1 // This file is (modified) from
|
rlm@1
|
2 // FCEUX (2009)
|
rlm@1
|
3 // FCE Ultra - NES/Famicom Emulator
|
rlm@1
|
4 // Copyright (C) 2003 Xodnizel
|
rlm@1
|
5 //
|
rlm@1
|
6 // This program is free software; you can redistribute it and/or modify
|
rlm@1
|
7 // it under the terms of the GNU General Public License as published by
|
rlm@1
|
8 // the Free Software Foundation; either version 2 of the License, or
|
rlm@1
|
9 // (at your option) any later version.
|
rlm@1
|
10 //
|
rlm@1
|
11 // This program is distributed in the hope that it will be useful,
|
rlm@1
|
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
|
rlm@1
|
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
rlm@1
|
14 // GNU General Public License for more details.
|
rlm@1
|
15 //
|
rlm@1
|
16 // You should have received a copy of the GNU General Public License
|
rlm@1
|
17 // along with this program; if not, write to the Free Software
|
rlm@1
|
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
rlm@1
|
19
|
rlm@1
|
20 #ifndef _7ZIPSTREAMS_HEADER
|
rlm@1
|
21 #define _7ZIPSTREAMS_HEADER
|
rlm@1
|
22
|
rlm@1
|
23 #include "7z/CPP/Common/MyCom.h"
|
rlm@1
|
24
|
rlm@1
|
25 class ICountedSequentialOutStream : public ISequentialOutStream
|
rlm@1
|
26 {
|
rlm@1
|
27 public:
|
rlm@1
|
28 virtual UINT32 Size() const = 0;
|
rlm@1
|
29 };
|
rlm@1
|
30
|
rlm@1
|
31 class SeqMemoryOutStream : public ICountedSequentialOutStream, private CMyUnknownImp
|
rlm@1
|
32 {
|
rlm@1
|
33 UINT8* const output;
|
rlm@1
|
34 UINT32 pos;
|
rlm@1
|
35 const UINT32 size;
|
rlm@1
|
36 ULONG refCount;
|
rlm@1
|
37
|
rlm@1
|
38 HRESULT STDMETHODCALLTYPE QueryInterface(REFGUID, void**)
|
rlm@1
|
39 {
|
rlm@1
|
40 return E_NOINTERFACE;
|
rlm@1
|
41 }
|
rlm@1
|
42
|
rlm@1
|
43 HRESULT STDMETHODCALLTYPE Write(const void* data, UInt32 length, UInt32* bytesWritten)
|
rlm@1
|
44 {
|
rlm@1
|
45 if (data != NULL || size == 0)
|
rlm@1
|
46 {
|
rlm@1
|
47 //assert(length <= size - pos);
|
rlm@1
|
48
|
rlm@1
|
49 if (length > size - pos)
|
rlm@1
|
50 length = size - pos;
|
rlm@1
|
51
|
rlm@1
|
52 if(data)
|
rlm@1
|
53 memcpy(output + pos, data, length);
|
rlm@1
|
54 pos += length;
|
rlm@1
|
55
|
rlm@1
|
56 if (bytesWritten)
|
rlm@1
|
57 *bytesWritten = length;
|
rlm@1
|
58
|
rlm@1
|
59 return S_OK;
|
rlm@1
|
60 }
|
rlm@1
|
61 else
|
rlm@1
|
62 {
|
rlm@1
|
63 return E_INVALIDARG;
|
rlm@1
|
64 }
|
rlm@1
|
65 }
|
rlm@1
|
66
|
rlm@1
|
67 MY_ADDREF_RELEASE
|
rlm@1
|
68
|
rlm@1
|
69 public:
|
rlm@1
|
70
|
rlm@1
|
71 SeqMemoryOutStream(void* d, UINT32 s) : output((UINT8*)d), pos(0), size(s), refCount(0) {}
|
rlm@1
|
72
|
rlm@1
|
73 virtual ~SeqMemoryOutStream()
|
rlm@1
|
74 {
|
rlm@1
|
75 int a = 0;
|
rlm@1
|
76 }
|
rlm@1
|
77
|
rlm@1
|
78 UINT32 Size() const
|
rlm@1
|
79 {
|
rlm@1
|
80 return pos;
|
rlm@1
|
81 }
|
rlm@1
|
82 };
|
rlm@1
|
83
|
rlm@1
|
84 class SeqFileOutStream : public ICountedSequentialOutStream, private CMyUnknownImp
|
rlm@1
|
85 {
|
rlm@1
|
86 FILE* file;
|
rlm@1
|
87 UINT32 pos;
|
rlm@1
|
88 ULONG refCount;
|
rlm@1
|
89
|
rlm@1
|
90 HRESULT STDMETHODCALLTYPE QueryInterface(REFGUID, void**)
|
rlm@1
|
91 {
|
rlm@1
|
92 return E_NOINTERFACE;
|
rlm@1
|
93 }
|
rlm@1
|
94
|
rlm@1
|
95 HRESULT STDMETHODCALLTYPE Write(const void* data, UInt32 length, UInt32* bytesWritten)
|
rlm@1
|
96 {
|
rlm@1
|
97 if(!file)
|
rlm@1
|
98 return E_FAIL;
|
rlm@1
|
99
|
rlm@1
|
100 if (data != NULL)
|
rlm@1
|
101 {
|
rlm@1
|
102 int written = 0;
|
rlm@1
|
103 if(data)
|
rlm@1
|
104 written = fwrite(data, 1, length, file);
|
rlm@1
|
105
|
rlm@1
|
106 pos += written;
|
rlm@1
|
107 if (bytesWritten)
|
rlm@1
|
108 *bytesWritten = written;
|
rlm@1
|
109
|
rlm@1
|
110 return S_OK;
|
rlm@1
|
111 }
|
rlm@1
|
112 else
|
rlm@1
|
113 {
|
rlm@1
|
114 return E_INVALIDARG;
|
rlm@1
|
115 }
|
rlm@1
|
116 }
|
rlm@1
|
117
|
rlm@1
|
118 MY_ADDREF_RELEASE
|
rlm@1
|
119
|
rlm@1
|
120 public:
|
rlm@1
|
121
|
rlm@1
|
122 SeqFileOutStream(const char* outFilename) : pos(0), refCount(0)
|
rlm@1
|
123 {
|
rlm@1
|
124 file = fopen(outFilename, "wb");
|
rlm@1
|
125 }
|
rlm@1
|
126 virtual ~SeqFileOutStream()
|
rlm@1
|
127 {
|
rlm@1
|
128 if(file)
|
rlm@1
|
129 fclose(file);
|
rlm@1
|
130 }
|
rlm@1
|
131
|
rlm@1
|
132 UINT32 Size() const
|
rlm@1
|
133 {
|
rlm@1
|
134 return pos;
|
rlm@1
|
135 }
|
rlm@1
|
136 };
|
rlm@1
|
137
|
rlm@1
|
138
|
rlm@1
|
139 class OutStream : public IArchiveExtractCallback, private CMyUnknownImp
|
rlm@1
|
140 {
|
rlm@1
|
141 ICountedSequentialOutStream* seqStream;
|
rlm@1
|
142 const UINT32 index;
|
rlm@1
|
143 ULONG refCount;
|
rlm@1
|
144
|
rlm@1
|
145 HRESULT STDMETHODCALLTYPE QueryInterface(REFGUID, void**)
|
rlm@1
|
146 {
|
rlm@1
|
147 return E_NOINTERFACE;
|
rlm@1
|
148 }
|
rlm@1
|
149
|
rlm@1
|
150 HRESULT STDMETHODCALLTYPE PrepareOperation(Int32)
|
rlm@1
|
151 {
|
rlm@1
|
152 return S_OK;
|
rlm@1
|
153 }
|
rlm@1
|
154
|
rlm@1
|
155 HRESULT STDMETHODCALLTYPE SetTotal(UInt64)
|
rlm@1
|
156 {
|
rlm@1
|
157 return S_OK;
|
rlm@1
|
158 }
|
rlm@1
|
159
|
rlm@1
|
160 HRESULT STDMETHODCALLTYPE SetCompleted(const UInt64*)
|
rlm@1
|
161 {
|
rlm@1
|
162 return S_OK;
|
rlm@1
|
163 }
|
rlm@1
|
164
|
rlm@1
|
165 HRESULT STDMETHODCALLTYPE SetOperationResult(Int32)
|
rlm@1
|
166 {
|
rlm@1
|
167 return S_OK;
|
rlm@1
|
168 }
|
rlm@1
|
169
|
rlm@1
|
170 HRESULT STDMETHODCALLTYPE GetStream(UInt32 id, ISequentialOutStream** ptr, Int32 mode)
|
rlm@1
|
171 {
|
rlm@1
|
172 switch (mode)
|
rlm@1
|
173 {
|
rlm@1
|
174 case NArchive::NExtract::NAskMode::kExtract:
|
rlm@1
|
175 case NArchive::NExtract::NAskMode::kTest:
|
rlm@1
|
176
|
rlm@1
|
177 if (id != index || ptr == NULL)
|
rlm@1
|
178 return S_FALSE;
|
rlm@1
|
179 else
|
rlm@1
|
180 *ptr = seqStream;
|
rlm@1
|
181 // fall through
|
rlm@1
|
182 case NArchive::NExtract::NAskMode::kSkip:
|
rlm@1
|
183 return S_OK;
|
rlm@1
|
184
|
rlm@1
|
185 default:
|
rlm@1
|
186 return E_INVALIDARG;
|
rlm@1
|
187 }
|
rlm@1
|
188 }
|
rlm@1
|
189
|
rlm@1
|
190 MY_ADDREF_RELEASE
|
rlm@1
|
191
|
rlm@1
|
192 public:
|
rlm@1
|
193
|
rlm@1
|
194 OutStream(UINT32 index, void* data, UINT32 size) : index(index), refCount(0)
|
rlm@1
|
195 {
|
rlm@1
|
196 seqStream = new SeqMemoryOutStream(data, size);
|
rlm@1
|
197 seqStream->AddRef();
|
rlm@1
|
198 }
|
rlm@1
|
199 OutStream(UINT32 index, const char* outFilename) : index(index), refCount(0)
|
rlm@1
|
200 {
|
rlm@1
|
201 seqStream = new SeqFileOutStream(outFilename);
|
rlm@1
|
202 seqStream->AddRef();
|
rlm@1
|
203 }
|
rlm@1
|
204 virtual ~OutStream()
|
rlm@1
|
205 {
|
rlm@1
|
206 //seqStream->Release(); // commented out because apparently IInArchive::Extract() calls Release one more time than it calls AddRef
|
rlm@1
|
207 }
|
rlm@1
|
208 UINT32 Size() const
|
rlm@1
|
209 {
|
rlm@1
|
210 return seqStream->Size();
|
rlm@1
|
211 }
|
rlm@1
|
212 };
|
rlm@1
|
213
|
rlm@1
|
214 class InStream : public IInStream, private IStreamGetSize, private CMyUnknownImp
|
rlm@1
|
215 {
|
rlm@1
|
216 ULONG refCount;
|
rlm@1
|
217
|
rlm@1
|
218 HRESULT STDMETHODCALLTYPE QueryInterface(REFGUID, void**)
|
rlm@1
|
219 {
|
rlm@1
|
220 return E_NOINTERFACE;
|
rlm@1
|
221 }
|
rlm@1
|
222
|
rlm@1
|
223 HRESULT STDMETHODCALLTYPE GetSize(UInt64* outSize)
|
rlm@1
|
224 {
|
rlm@1
|
225 if (outSize)
|
rlm@1
|
226 {
|
rlm@1
|
227 *outSize = size;
|
rlm@1
|
228 return S_OK;
|
rlm@1
|
229 }
|
rlm@1
|
230 else
|
rlm@1
|
231 {
|
rlm@1
|
232 return E_INVALIDARG;
|
rlm@1
|
233 }
|
rlm@1
|
234 }
|
rlm@1
|
235
|
rlm@1
|
236 MY_ADDREF_RELEASE
|
rlm@1
|
237
|
rlm@1
|
238 protected:
|
rlm@1
|
239
|
rlm@1
|
240 UINT32 size;
|
rlm@1
|
241
|
rlm@1
|
242 public:
|
rlm@1
|
243
|
rlm@1
|
244 explicit InStream() : refCount(0) {}
|
rlm@1
|
245 virtual ~InStream() {}
|
rlm@1
|
246 };
|
rlm@1
|
247
|
rlm@1
|
248
|
rlm@1
|
249 class InFileStream : public InStream
|
rlm@1
|
250 {
|
rlm@1
|
251 public:
|
rlm@1
|
252
|
rlm@1
|
253 virtual ~InFileStream()
|
rlm@1
|
254 {
|
rlm@1
|
255 if(file)
|
rlm@1
|
256 fclose(file);
|
rlm@1
|
257 }
|
rlm@1
|
258
|
rlm@1
|
259 FILE* file;
|
rlm@1
|
260
|
rlm@1
|
261 InFileStream(const char* fname) : file(NULL)
|
rlm@1
|
262 {
|
rlm@1
|
263 file = fopen(fname, "rb");
|
rlm@1
|
264 if(file)
|
rlm@1
|
265 {
|
rlm@1
|
266 fseek(file, 0, SEEK_END);
|
rlm@1
|
267 size = ftell(file);
|
rlm@1
|
268 fseek(file, 0, SEEK_SET);
|
rlm@1
|
269 }
|
rlm@1
|
270 }
|
rlm@1
|
271
|
rlm@1
|
272 HRESULT STDMETHODCALLTYPE Read(void* data, UInt32 length, UInt32* bytesRead)
|
rlm@1
|
273 {
|
rlm@1
|
274 if(!file)
|
rlm@1
|
275 return E_FAIL;
|
rlm@1
|
276
|
rlm@1
|
277 if (data != NULL || length == 0)
|
rlm@1
|
278 {
|
rlm@1
|
279 int read = fread(data, 1, length, file);
|
rlm@1
|
280
|
rlm@1
|
281 if (bytesRead)
|
rlm@1
|
282 *bytesRead = read;
|
rlm@1
|
283
|
rlm@1
|
284 return S_OK;
|
rlm@1
|
285 }
|
rlm@1
|
286 else
|
rlm@1
|
287 {
|
rlm@1
|
288 return E_INVALIDARG;
|
rlm@1
|
289 }
|
rlm@1
|
290 }
|
rlm@1
|
291
|
rlm@1
|
292 HRESULT STDMETHODCALLTYPE Seek(Int64 offset, UInt32 origin, UInt64* pos)
|
rlm@1
|
293 {
|
rlm@1
|
294 if(!file)
|
rlm@1
|
295 return E_FAIL;
|
rlm@1
|
296
|
rlm@1
|
297 if (origin < 3)
|
rlm@1
|
298 {
|
rlm@1
|
299 fseek(file, (long)offset, origin);
|
rlm@1
|
300 origin = ftell(file);
|
rlm@1
|
301
|
rlm@1
|
302 if (pos)
|
rlm@1
|
303 *pos = origin;
|
rlm@1
|
304
|
rlm@1
|
305 return S_OK;
|
rlm@1
|
306 }
|
rlm@1
|
307 else
|
rlm@1
|
308 {
|
rlm@1
|
309 return E_INVALIDARG;
|
rlm@1
|
310 }
|
rlm@1
|
311
|
rlm@1
|
312 }
|
rlm@1
|
313 };
|
rlm@1
|
314
|
rlm@1
|
315 #endif
|