--- /dev/null +++ C/LZMA_ZLibCompat.h @@ -0,0 +1,39 @@ +#ifndef LZMA_ZLibCompat +#define LZMA_ZLibCompat + +#include + +#include + +/* CLzmaEncProps */ +#define ZLIB_COMPAT__THE_ONLY_SUPPORTED_COMPRESSION_LEVEL 9 +#define ZLIB_COMPAT__DICT_SIZE (1 << (ZLIB_COMPAT__THE_ONLY_SUPPORTED_COMPRESSION_LEVEL + 14)) +#define ZLIB_COMPAT__LC 3 +#define ZLIB_COMPAT__LP 0 +#define ZLIB_COMPAT__PB 2 +#define ZLIB_COMPAT__ALGO 2 +#define ZLIB_COMPAT__FB 128 +#define ZLIB_COMPAT__MATCH_FINDER_MODE ((const wchar_t *)L"BT4") /* BinTree-mode with numHashBytes=4 */ +#define ZLIB_COMPAT__MC 0 /* 0 means "use default autocalculated value", autocalculated from fb and btMode values, see LzmaEncProps_Normalize for details */ +#define ZLIB_COMPAT__WRITE_END_MARK 1 + +#define LZMA_ZLIB_COMPAT(name) name##_lzma_zlib_compat + +#ifdef __cplusplus +extern "C" { +#endif + +typedef int (*zlib_compress_t) (Bytef * , uLongf * , const Bytef * , uLong ); +ZEXTERN int ZEXPORT LZMA_ZLIB_COMPAT(compress) (Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen); + +typedef int (*zlib_compress2_t) (Bytef * , uLongf * , const Bytef * , uLong , int ); +ZEXTERN int ZEXPORT LZMA_ZLIB_COMPAT(compress2) (Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen, int level); + +typedef int (*zlib_uncompress_t) (Bytef * , uLongf * , const Bytef * , uLong ); +ZEXTERN int ZEXPORT LZMA_ZLIB_COMPAT(uncompress) (Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen); + +#ifdef __cplusplus +} +#endif + +#endif --- C/LzmaLib/makefile.gcc +++ C/LzmaLib/makefile.gcc @@ -17,6 +17,8 @@ LzmaEnc.o \ LzmaLib.o +OBJS += LZMA_ZLibCompat.o + all: $(PROG) $(PROG): $(OBJS) --- /dev/null +++ C/LZMA_ZLibCompat.c @@ -0,0 +1,105 @@ +#include + +#include "LZMA_ZLibCompat.h" + +#include "Types.h" +#include "LzmaLib.h" + +#ifdef __cplusplus +extern "C" { +#endif + +ZEXTERN int ZEXPORT LZMA_ZLIB_COMPAT(compress) (Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen) { + return LZMA_ZLIB_COMPAT(compress2)(dest, destLen, source, sourceLen, ZLIB_COMPAT__THE_ONLY_SUPPORTED_COMPRESSION_LEVEL); +} + +/* + compress2 returns (taken from zlib.h) + - Z_OK if success, + - Z_MEM_ERROR if there was not enough memory, + - Z_BUF_ERROR if there was not enough room in the output buffer, + - Z_STREAM_ERROR if the level parameter is invalid. +*/ +ZEXTERN int ZEXPORT LZMA_ZLIB_COMPAT(compress2) (Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen, int level) { + if (level != ZLIB_COMPAT__THE_ONLY_SUPPORTED_COMPRESSION_LEVEL) { + return Z_STREAM_ERROR; + } + + Byte props[LZMA_PROPS_SIZE]; + size_t propsSize = LZMA_PROPS_SIZE; + SRes result = LzmaCompress( + dest, + (size_t*)destLen, + source, + sourceLen, + props, + &propsSize, + level, + ZLIB_COMPAT__DICT_SIZE, + ZLIB_COMPAT__LC, + ZLIB_COMPAT__LP, + ZLIB_COMPAT__PB, + ZLIB_COMPAT__ALGO, + ZLIB_COMPAT__FB, + ZLIB_COMPAT__MATCH_FINDER_MODE, + ZLIB_COMPAT__MC, + ZLIB_COMPAT__WRITE_END_MARK, + 1 /* numThreads */ + ); + + if (result != SZ_OK) { + fprintf(stderr, "%s failed with code=%d\n", __FUNCTION__, result); + } + + switch (result) { + case SZ_ERROR_MEM: + return Z_MEM_ERROR; + case SZ_ERROR_PARAM: + return Z_STREAM_ERROR; + case SZ_ERROR_OUTPUT_EOF: /* output buffer overflow */ + return Z_BUF_ERROR; + default: + return (result == SZ_OK) ? Z_OK : Z_BUF_ERROR; + } +} + +ZEXTERN int ZEXPORT LZMA_ZLIB_COMPAT(uncompress) (Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen) { + Byte props[LZMA_PROPS_SIZE]; + { + int i; + UInt32 dictSize = ZLIB_COMPAT__DICT_SIZE; + props[0] = (Byte)((ZLIB_COMPAT__PB * 5 + ZLIB_COMPAT__LP) * 9 + ZLIB_COMPAT__LC); + for (i = 1; i> (8 * (i-1))); + } + } + + size_t processedLen = sourceLen; + SRes result = LzmaUncompress( + dest, + (size_t*)destLen, + source, + &processedLen, + props, + LZMA_PROPS_SIZE + ); + + if (sourceLen - processedLen > 7) { /* TODO: understand where these 5 till 7 extra bytes come from - props encoded within the stream ? */ + fprintf(stderr, "%s: warning sourceLen!=processedLen, sourceLen = %lu, processedLen = %zu, delta = %ld\n", __FUNCTION__, sourceLen, processedLen, sourceLen-processedLen); + } + + switch (result) { + case SZ_ERROR_MEM: + return Z_MEM_ERROR; + case SZ_ERROR_DATA: /* data error */ + case SZ_ERROR_INPUT_EOF: /* unexpected EOF in input buffer, i.e. decoder expects more bytes in input buffer */ + case SZ_ERROR_UNSUPPORTED: /* unsupported properties */ + return Z_DATA_ERROR; + default: + return (result == SZ_OK /*&& sourceLen == processedLen*/) ? Z_OK : Z_DATA_ERROR; + } +} + +#ifdef __cplusplus +} +#endif --- CPP/7zip/Compress/LZMA_Lib/makefile.gcc +++ CPP/7zip/Compress/LZMA_Lib/makefile.gcc @@ -37,6 +37,8 @@ StringToInt.o \ MyVector.o +CPP_OBJS += LZMA_ZLibCompat.o + all: $(PROG) $(PROG): $(C_OBJS) $(CPP_OBJS) --- /dev/null +++ CPP/7zip/Compress/LZMA_ZLibCompat.cpp @@ -0,0 +1,271 @@ +/* + * lzma zlib simplified wrapper + * + * Copyright (c) 2005-2006 Oleg I. Vdovikin + * + * This library is free software; you can redistribute + * it and/or modify it under the terms of the GNU Lesser + * General Public License as published by the Free Software + * Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, write to + * the Free Software Foundation, Inc., 59 Temple Place, + * Suite 330, Boston, MA 02111-1307 USA + */ + +#include "LZMA_ZLibCompat.h" + +#ifdef WIN32 +#include +#else +#define INITGUID +#endif + +#include "../../Common/MyWindows.h" +#include "LzmaDecoder.h" +#include "LzmaEncoder.h" + +#define STG_E_SEEKERROR ((HRESULT)0x80030019L) +#define STG_E_MEDIUMFULL ((HRESULT)0x80030070L) + +class CInMemoryStream: + public IInStream, + public IStreamGetSize, + public CMyUnknownImp +{ +public: + CInMemoryStream(const Bytef *data, UInt64 size) : + m_data(data), m_size(size), m_offset(0) {} + + virtual ~CInMemoryStream() {} + + MY_UNKNOWN_IMP2(IInStream, IStreamGetSize) + + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize) + { + if (size > m_size - m_offset) + size = m_size - m_offset; + + if (size) { + memcpy(data, m_data + m_offset, size); + } + + m_offset += size; + + if (processedSize) + *processedSize = size; + + return S_OK; + } + + STDMETHOD(ReadPart)(void *data, UInt32 size, UInt32 *processedSize) + { + return Read(data, size, processedSize); + } + + STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) + { + Int64 _offset; + + if (seekOrigin == STREAM_SEEK_SET) _offset = offset; + else if (seekOrigin == STREAM_SEEK_CUR) _offset = m_offset + offset; + else if (seekOrigin == STREAM_SEEK_END) _offset = m_size; + else return STG_E_INVALIDFUNCTION; + + if (_offset < 0 || ((UInt64)_offset) > m_size) + return STG_E_SEEKERROR; + + m_offset = _offset; + + if (newPosition) + *newPosition = m_offset; + + return S_OK; + } + + STDMETHOD(GetSize)(UInt64 *size) + { + *size = m_size; + return S_OK; + } +protected: + const Bytef *m_data; + UInt64 m_size; + UInt64 m_offset; +}; + +class COutMemoryStream: + public IOutStream, + public CMyUnknownImp +{ +public: + COutMemoryStream(Bytef *data, UInt64 maxsize) : + m_data(data), m_size(0), m_maxsize(maxsize), m_offset(0) {} + virtual ~COutMemoryStream() {} + + MY_UNKNOWN_IMP1(IOutStream) + + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize) + { + if (size > m_maxsize - m_offset) + size = m_maxsize - m_offset; + + if (size) { + memcpy(m_data + m_offset, data, size); + } + + m_offset += size; + + if (m_offset > m_size) + m_size = m_offset; + + if (processedSize) + *processedSize = size; + + return S_OK; + } + + STDMETHOD(WritePart)(const void *data, UInt32 size, UInt32 *processedSize) + { + return Write(data, size, processedSize); + } + + STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) + { + Int64 _offset; + + if (seekOrigin == STREAM_SEEK_SET) _offset = offset; + else if (seekOrigin == STREAM_SEEK_CUR) _offset = m_offset + offset; + else if (seekOrigin == STREAM_SEEK_END) _offset = m_size; + else return STG_E_INVALIDFUNCTION; + + if (_offset < 0 || ((UInt64)_offset) > m_maxsize) + return STG_E_SEEKERROR; + + m_offset = _offset; + + if (newPosition) + *newPosition = m_offset; + + return S_OK; + } + + STDMETHOD(SetSize)(Int64 newSize) + { + if ((UInt64)newSize > m_maxsize) + return STG_E_MEDIUMFULL; + + return S_OK; + } +protected: + Bytef *m_data; + UInt64 m_size; + UInt64 m_maxsize; + UInt64 m_offset; +}; + +#ifdef __cplusplus +extern "C" { +#endif + +ZEXTERN int ZEXPORT LZMA_ZLIB_COMPAT(compress) (Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen) { + return LZMA_ZLIB_COMPAT(compress2)(dest, destLen, source, sourceLen, ZLIB_COMPAT__THE_ONLY_SUPPORTED_COMPRESSION_LEVEL); +} + +ZEXTERN int ZEXPORT LZMA_ZLIB_COMPAT(compress2) (Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen, int level) { + if (level != ZLIB_COMPAT__THE_ONLY_SUPPORTED_COMPRESSION_LEVEL) { + return Z_STREAM_ERROR; + } + + CInMemoryStream *inStreamSpec = new CInMemoryStream(source, sourceLen); + CMyComPtr inStream = inStreamSpec; + + COutMemoryStream *outStreamSpec = new COutMemoryStream(dest, *destLen); + CMyComPtr outStream = outStreamSpec; + + NCompress::NLzma::CEncoder *encoderSpec = + new NCompress::NLzma::CEncoder; + CMyComPtr encoder = encoderSpec; + + PROPID propIDs[] = + { + NCoderPropID::kDictionarySize, + NCoderPropID::kPosStateBits, + NCoderPropID::kLitContextBits, + NCoderPropID::kLitPosBits, + NCoderPropID::kAlgorithm, + NCoderPropID::kNumFastBytes, + NCoderPropID::kMatchFinder, + NCoderPropID::kEndMarker + }; + const int kNumProps = sizeof(propIDs) / sizeof(propIDs[0]); + + PROPVARIANT properties[kNumProps]; + for (int p = 0; p < 6; p++) + properties[p].vt = VT_UI4; + properties[0].ulVal = UInt32(ZLIB_COMPAT__DICT_SIZE); // kDictionarySize + properties[1].ulVal = UInt32(ZLIB_COMPAT__PB); // kPosStateBits + properties[2].ulVal = UInt32(ZLIB_COMPAT__LC); // kLitContextBits + properties[3].ulVal = UInt32(ZLIB_COMPAT__LP); // kLitPosBits + properties[4].ulVal = UInt32(ZLIB_COMPAT__ALGO); // kAlgorithm + properties[5].ulVal = UInt32(ZLIB_COMPAT__FB); // kNumFastBytes + + properties[6].vt = VT_BSTR; + properties[6].bstrVal = (BSTR)ZLIB_COMPAT__MATCH_FINDER_MODE; // kMatchFinder + + properties[7].vt = VT_BOOL; + properties[7].boolVal = ZLIB_COMPAT__WRITE_END_MARK ? VARIANT_TRUE : VARIANT_FALSE; // kEndMarker + + if (encoderSpec->SetCoderProperties(propIDs, properties, kNumProps) != S_OK) + return Z_MEM_ERROR; + + HRESULT result = encoder->Code(inStream, outStream, 0, 0, 0); + if (result == E_OUTOFMEMORY) { + return Z_MEM_ERROR; + } else if (result != S_OK) { + return Z_BUF_ERROR; + } + + UInt64 fileSize; + outStreamSpec->Seek(0, STREAM_SEEK_END, &fileSize); + *destLen = fileSize; + + return Z_OK; +} + +ZEXTERN int ZEXPORT LZMA_ZLIB_COMPAT(uncompress) (Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen) { + CInMemoryStream *inStreamSpec = new CInMemoryStream(source, sourceLen); + CMyComPtr inStream = inStreamSpec; + + COutMemoryStream *outStreamSpec = new COutMemoryStream(dest, *destLen); + CMyComPtr outStream = outStreamSpec; + + NCompress::NLzma::CDecoder *decoderSpec = new NCompress::NLzma::CDecoder; + CMyComPtr decoder = decoderSpec; + + if (decoderSpec->SetDecoderPropertiesRaw(ZLIB_COMPAT__LC, ZLIB_COMPAT__LP, ZLIB_COMPAT__PB, ZLIB_COMPAT__DICT_SIZE) != S_OK) { + return Z_DATA_ERROR; + } + + UInt64 fileSize = *destLen; + if (decoder->Code(inStream, outStream, 0, &fileSize, 0) != S_OK) { + return Z_DATA_ERROR; + } + + outStreamSpec->Seek(0, STREAM_SEEK_END, &fileSize); + *destLen = fileSize; + + return Z_OK; +} + +#ifdef __cplusplus +} +#endif