view src/win32/7zip/7zipstreams.h @ 1:f9f4f1b99eed

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