annotate 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
rev   line source
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