rlm@1: // This file is (modified) from rlm@1: // FCEUX (2009) rlm@1: // FCE Ultra - NES/Famicom Emulator rlm@1: // Copyright (C) 2003 Xodnizel rlm@1: // rlm@1: // This program is free software; you can redistribute it and/or modify rlm@1: // it under the terms of the GNU General Public License as published by rlm@1: // the Free Software Foundation; either version 2 of the License, or rlm@1: // (at your option) any later version. rlm@1: // rlm@1: // This program is distributed in the hope that it will be useful, rlm@1: // but WITHOUT ANY WARRANTY; without even the implied warranty of rlm@1: // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the rlm@1: // GNU General Public License for more details. rlm@1: // rlm@1: // You should have received a copy of the GNU General Public License rlm@1: // along with this program; if not, write to the Free Software rlm@1: // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA rlm@1: rlm@1: #ifndef _7ZIPSTREAMS_HEADER rlm@1: #define _7ZIPSTREAMS_HEADER rlm@1: rlm@1: #include "7z/CPP/Common/MyCom.h" rlm@1: rlm@1: class ICountedSequentialOutStream : public ISequentialOutStream rlm@1: { rlm@1: public: rlm@1: virtual UINT32 Size() const = 0; rlm@1: }; rlm@1: rlm@1: class SeqMemoryOutStream : public ICountedSequentialOutStream, private CMyUnknownImp rlm@1: { rlm@1: UINT8* const output; rlm@1: UINT32 pos; rlm@1: const UINT32 size; rlm@1: ULONG refCount; rlm@1: rlm@1: HRESULT STDMETHODCALLTYPE QueryInterface(REFGUID, void**) rlm@1: { rlm@1: return E_NOINTERFACE; rlm@1: } rlm@1: rlm@1: HRESULT STDMETHODCALLTYPE Write(const void* data, UInt32 length, UInt32* bytesWritten) rlm@1: { rlm@1: if (data != NULL || size == 0) rlm@1: { rlm@1: //assert(length <= size - pos); rlm@1: rlm@1: if (length > size - pos) rlm@1: length = size - pos; rlm@1: rlm@1: if(data) rlm@1: memcpy(output + pos, data, length); rlm@1: pos += length; rlm@1: rlm@1: if (bytesWritten) rlm@1: *bytesWritten = length; rlm@1: rlm@1: return S_OK; rlm@1: } rlm@1: else rlm@1: { rlm@1: return E_INVALIDARG; rlm@1: } rlm@1: } rlm@1: rlm@1: MY_ADDREF_RELEASE rlm@1: rlm@1: public: rlm@1: rlm@1: SeqMemoryOutStream(void* d, UINT32 s) : output((UINT8*)d), pos(0), size(s), refCount(0) {} rlm@1: rlm@1: virtual ~SeqMemoryOutStream() rlm@1: { rlm@1: int a = 0; rlm@1: } rlm@1: rlm@1: UINT32 Size() const rlm@1: { rlm@1: return pos; rlm@1: } rlm@1: }; rlm@1: rlm@1: class SeqFileOutStream : public ICountedSequentialOutStream, private CMyUnknownImp rlm@1: { rlm@1: FILE* file; rlm@1: UINT32 pos; rlm@1: ULONG refCount; rlm@1: rlm@1: HRESULT STDMETHODCALLTYPE QueryInterface(REFGUID, void**) rlm@1: { rlm@1: return E_NOINTERFACE; rlm@1: } rlm@1: rlm@1: HRESULT STDMETHODCALLTYPE Write(const void* data, UInt32 length, UInt32* bytesWritten) rlm@1: { rlm@1: if(!file) rlm@1: return E_FAIL; rlm@1: rlm@1: if (data != NULL) rlm@1: { rlm@1: int written = 0; rlm@1: if(data) rlm@1: written = fwrite(data, 1, length, file); rlm@1: rlm@1: pos += written; rlm@1: if (bytesWritten) rlm@1: *bytesWritten = written; rlm@1: rlm@1: return S_OK; rlm@1: } rlm@1: else rlm@1: { rlm@1: return E_INVALIDARG; rlm@1: } rlm@1: } rlm@1: rlm@1: MY_ADDREF_RELEASE rlm@1: rlm@1: public: rlm@1: rlm@1: SeqFileOutStream(const char* outFilename) : pos(0), refCount(0) rlm@1: { rlm@1: file = fopen(outFilename, "wb"); rlm@1: } rlm@1: virtual ~SeqFileOutStream() rlm@1: { rlm@1: if(file) rlm@1: fclose(file); rlm@1: } rlm@1: rlm@1: UINT32 Size() const rlm@1: { rlm@1: return pos; rlm@1: } rlm@1: }; rlm@1: rlm@1: rlm@1: class OutStream : public IArchiveExtractCallback, private CMyUnknownImp rlm@1: { rlm@1: ICountedSequentialOutStream* seqStream; rlm@1: const UINT32 index; rlm@1: ULONG refCount; rlm@1: rlm@1: HRESULT STDMETHODCALLTYPE QueryInterface(REFGUID, void**) rlm@1: { rlm@1: return E_NOINTERFACE; rlm@1: } rlm@1: rlm@1: HRESULT STDMETHODCALLTYPE PrepareOperation(Int32) rlm@1: { rlm@1: return S_OK; rlm@1: } rlm@1: rlm@1: HRESULT STDMETHODCALLTYPE SetTotal(UInt64) rlm@1: { rlm@1: return S_OK; rlm@1: } rlm@1: rlm@1: HRESULT STDMETHODCALLTYPE SetCompleted(const UInt64*) rlm@1: { rlm@1: return S_OK; rlm@1: } rlm@1: rlm@1: HRESULT STDMETHODCALLTYPE SetOperationResult(Int32) rlm@1: { rlm@1: return S_OK; rlm@1: } rlm@1: rlm@1: HRESULT STDMETHODCALLTYPE GetStream(UInt32 id, ISequentialOutStream** ptr, Int32 mode) rlm@1: { rlm@1: switch (mode) rlm@1: { rlm@1: case NArchive::NExtract::NAskMode::kExtract: rlm@1: case NArchive::NExtract::NAskMode::kTest: rlm@1: rlm@1: if (id != index || ptr == NULL) rlm@1: return S_FALSE; rlm@1: else rlm@1: *ptr = seqStream; rlm@1: // fall through rlm@1: case NArchive::NExtract::NAskMode::kSkip: rlm@1: return S_OK; rlm@1: rlm@1: default: rlm@1: return E_INVALIDARG; rlm@1: } rlm@1: } rlm@1: rlm@1: MY_ADDREF_RELEASE rlm@1: rlm@1: public: rlm@1: rlm@1: OutStream(UINT32 index, void* data, UINT32 size) : index(index), refCount(0) rlm@1: { rlm@1: seqStream = new SeqMemoryOutStream(data, size); rlm@1: seqStream->AddRef(); rlm@1: } rlm@1: OutStream(UINT32 index, const char* outFilename) : index(index), refCount(0) rlm@1: { rlm@1: seqStream = new SeqFileOutStream(outFilename); rlm@1: seqStream->AddRef(); rlm@1: } rlm@1: virtual ~OutStream() rlm@1: { rlm@1: //seqStream->Release(); // commented out because apparently IInArchive::Extract() calls Release one more time than it calls AddRef rlm@1: } rlm@1: UINT32 Size() const rlm@1: { rlm@1: return seqStream->Size(); rlm@1: } rlm@1: }; rlm@1: rlm@1: class InStream : public IInStream, private IStreamGetSize, private CMyUnknownImp rlm@1: { rlm@1: ULONG refCount; rlm@1: rlm@1: HRESULT STDMETHODCALLTYPE QueryInterface(REFGUID, void**) rlm@1: { rlm@1: return E_NOINTERFACE; rlm@1: } rlm@1: rlm@1: HRESULT STDMETHODCALLTYPE GetSize(UInt64* outSize) rlm@1: { rlm@1: if (outSize) rlm@1: { rlm@1: *outSize = size; rlm@1: return S_OK; rlm@1: } rlm@1: else rlm@1: { rlm@1: return E_INVALIDARG; rlm@1: } rlm@1: } rlm@1: rlm@1: MY_ADDREF_RELEASE rlm@1: rlm@1: protected: rlm@1: rlm@1: UINT32 size; rlm@1: rlm@1: public: rlm@1: rlm@1: explicit InStream() : refCount(0) {} rlm@1: virtual ~InStream() {} rlm@1: }; rlm@1: rlm@1: rlm@1: class InFileStream : public InStream rlm@1: { rlm@1: public: rlm@1: rlm@1: virtual ~InFileStream() rlm@1: { rlm@1: if(file) rlm@1: fclose(file); rlm@1: } rlm@1: rlm@1: FILE* file; rlm@1: rlm@1: InFileStream(const char* fname) : file(NULL) rlm@1: { rlm@1: file = fopen(fname, "rb"); rlm@1: if(file) rlm@1: { rlm@1: fseek(file, 0, SEEK_END); rlm@1: size = ftell(file); rlm@1: fseek(file, 0, SEEK_SET); rlm@1: } rlm@1: } rlm@1: rlm@1: HRESULT STDMETHODCALLTYPE Read(void* data, UInt32 length, UInt32* bytesRead) rlm@1: { rlm@1: if(!file) rlm@1: return E_FAIL; rlm@1: rlm@1: if (data != NULL || length == 0) rlm@1: { rlm@1: int read = fread(data, 1, length, file); rlm@1: rlm@1: if (bytesRead) rlm@1: *bytesRead = read; rlm@1: rlm@1: return S_OK; rlm@1: } rlm@1: else rlm@1: { rlm@1: return E_INVALIDARG; rlm@1: } rlm@1: } rlm@1: rlm@1: HRESULT STDMETHODCALLTYPE Seek(Int64 offset, UInt32 origin, UInt64* pos) rlm@1: { rlm@1: if(!file) rlm@1: return E_FAIL; rlm@1: rlm@1: if (origin < 3) rlm@1: { rlm@1: fseek(file, (long)offset, origin); rlm@1: origin = ftell(file); rlm@1: rlm@1: if (pos) rlm@1: *pos = origin; rlm@1: rlm@1: return S_OK; rlm@1: } rlm@1: else rlm@1: { rlm@1: return E_INVALIDARG; rlm@1: } rlm@1: rlm@1: } rlm@1: }; rlm@1: rlm@1: #endif