1/* 2 * lzma zlib simplified wrapper 3 * 4 * Copyright (c) 2005 Oleg I. Vdovikin <oleg@cs.msu.su> 5 * 6 * This library is free software; you can redistribute 7 * it and/or modify it under the terms of the GNU Lesser 8 * General Public License as published by the Free Software 9 * Foundation; either version 2.1 of the License, or 10 * (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be 13 * useful, but WITHOUT ANY WARRANTY; without even the implied 14 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 15 * PURPOSE. See the GNU Lesser General Public License 16 * for more details. 17 * 18 * You should have received a copy of the GNU Lesser General 19 * Public License along with this library; if not, write to 20 * the Free Software Foundation, Inc., 59 Temple Place, 21 * Suite 330, Boston, MA 02111-1307 USA 22 */ 23 24/* 25 * default values for encoder/decoder used by wrapper 26 */ 27 28#include <zlib.h> 29 30#define ZLIB_LC 3 31#define ZLIB_LP 0 32#define ZLIB_PB 2 33 34#ifdef WIN32 35#include <initguid.h> 36#else 37#define INITGUID 38#endif 39 40#include "../../../Common/MyWindows.h" 41#include "../LZMA/LZMADecoder.h" 42#include "../LZMA/LZMAEncoder.h" 43 44#define STG_E_SEEKERROR ((HRESULT)0x80030019L) 45#define STG_E_MEDIUMFULL ((HRESULT)0x80030070L) 46 47class CInMemoryStream: 48 public IInStream, 49 public IStreamGetSize, 50 public CMyUnknownImp 51{ 52public: 53 CInMemoryStream(const Bytef *data, UInt64 size) : 54 m_data(data), m_size(size), m_offset(0) {} 55 56 virtual ~CInMemoryStream() {} 57 58 MY_UNKNOWN_IMP2(IInStream, IStreamGetSize) 59 60 STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize) 61 { 62 if (size > m_size - m_offset) 63 size = m_size - m_offset; 64 65 if (size) { 66 memcpy(data, m_data + m_offset, size); 67 } 68 69 m_offset += size; 70 71 if (processedSize) 72 *processedSize = size; 73 74 return S_OK; 75 } 76 77 STDMETHOD(ReadPart)(void *data, UInt32 size, UInt32 *processedSize) 78 { 79 return Read(data, size, processedSize); 80 } 81 82 STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) 83 { 84 UInt64 _offset; 85 86 if (seekOrigin == STREAM_SEEK_SET) _offset = offset; 87 else if (seekOrigin == STREAM_SEEK_CUR) _offset = m_offset + offset; 88 else if (seekOrigin == STREAM_SEEK_END) _offset = m_size; 89 else return STG_E_INVALIDFUNCTION; 90 91 if (_offset < 0 || _offset > m_size) 92 return STG_E_SEEKERROR; 93 94 m_offset = _offset; 95 96 if (newPosition) 97 *newPosition = m_offset; 98 99 return S_OK; 100 } 101 102 STDMETHOD(GetSize)(UInt64 *size) 103 { 104 *size = m_size; 105 return S_OK; 106 } 107protected: 108 const Bytef *m_data; 109 UInt64 m_size; 110 UInt64 m_offset; 111}; 112 113class COutMemoryStream: 114 public IOutStream, 115 public CMyUnknownImp 116{ 117public: 118 COutMemoryStream(Bytef *data, UInt64 maxsize) : 119 m_data(data), m_size(0), m_maxsize(maxsize), m_offset(0) {} 120 virtual ~COutMemoryStream() {} 121 122 MY_UNKNOWN_IMP1(IOutStream) 123 124 STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize) 125 { 126 if (size > m_maxsize - m_offset) 127 size = m_maxsize - m_offset; 128 129 if (size) { 130 memcpy(m_data + m_offset, data, size); 131 } 132 133 m_offset += size; 134 135 if (m_offset > m_size) 136 m_size = m_offset; 137 138 if (processedSize) 139 *processedSize = size; 140 141 return S_OK; 142 } 143 144 STDMETHOD(WritePart)(const void *data, UInt32 size, UInt32 *processedSize) 145 { 146 return Write(data, size, processedSize); 147 } 148 149 STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) 150 { 151 UInt64 _offset; 152 153 if (seekOrigin == STREAM_SEEK_SET) _offset = offset; 154 else if (seekOrigin == STREAM_SEEK_CUR) _offset = m_offset + offset; 155 else if (seekOrigin == STREAM_SEEK_END) _offset = m_size; 156 else return STG_E_INVALIDFUNCTION; 157 158 if (_offset < 0 || _offset > m_maxsize) 159 return STG_E_SEEKERROR; 160 161 m_offset = _offset; 162 163 if (newPosition) 164 *newPosition = m_offset; 165 166 return S_OK; 167 } 168 169 STDMETHOD(SetSize)(Int64 newSize) 170 { 171 if ((UInt64)newSize > m_maxsize) 172 return STG_E_MEDIUMFULL; 173 174 return S_OK; 175 } 176protected: 177 Bytef *m_data; 178 UInt64 m_size; 179 UInt64 m_maxsize; 180 UInt64 m_offset; 181}; 182 183ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, 184 const Bytef *source, uLong sourceLen, 185 int level)) 186{ 187 CInMemoryStream *inStreamSpec = new CInMemoryStream(source, sourceLen); 188 CMyComPtr<ISequentialInStream> inStream = inStreamSpec; 189 190 COutMemoryStream *outStreamSpec = new COutMemoryStream(dest, *destLen); 191 CMyComPtr<ISequentialOutStream> outStream = outStreamSpec; 192 193 NCompress::NLZMA::CEncoder *encoderSpec = 194 new NCompress::NLZMA::CEncoder; 195 CMyComPtr<ICompressCoder> encoder = encoderSpec; 196 197 PROPID propIDs[] = 198 { 199 NCoderPropID::kDictionarySize, 200 NCoderPropID::kPosStateBits, 201 NCoderPropID::kLitContextBits, 202 NCoderPropID::kLitPosBits, 203 NCoderPropID::kAlgorithm, 204 NCoderPropID::kNumFastBytes, 205 NCoderPropID::kMatchFinder, 206 NCoderPropID::kEndMarker 207 }; 208 const int kNumProps = sizeof(propIDs) / sizeof(propIDs[0]); 209 210 PROPVARIANT properties[kNumProps]; 211 for (int p = 0; p < 6; p++) 212 properties[p].vt = VT_UI4; 213 properties[0].ulVal = UInt32(1 << (level + 14)); 214 properties[1].ulVal = UInt32(ZLIB_PB); 215 properties[2].ulVal = UInt32(ZLIB_LC); // for normal files 216 properties[3].ulVal = UInt32(ZLIB_LP); // for normal files 217 properties[4].ulVal = UInt32(1); 218 properties[5].ulVal = UInt32(128); 219 220 properties[6].vt = VT_BSTR; 221 properties[6].bstrVal = (BSTR)(const wchar_t *)L"BT2"; 222 223 properties[7].vt = VT_BOOL; 224 properties[7].boolVal = VARIANT_TRUE; 225 226 if (encoderSpec->SetCoderProperties(propIDs, properties, kNumProps) != S_OK) 227 return Z_MEM_ERROR; // should not happen 228 229 HRESULT result = encoder->Code(inStream, outStream, 0, 0, 0); 230 if (result == E_OUTOFMEMORY) 231 { 232 return Z_MEM_ERROR; 233 } 234 else if (result != S_OK) 235 { 236 return Z_BUF_ERROR; // should not happen 237 } 238 239 UInt64 fileSize; 240 outStreamSpec->Seek(0, STREAM_SEEK_END, &fileSize); 241 *destLen = fileSize; 242 243 return Z_OK; 244} 245 246ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, 247 const Bytef *source, uLong sourceLen)) 248{ 249 CInMemoryStream *inStreamSpec = new CInMemoryStream(source, sourceLen); 250 CMyComPtr<ISequentialInStream> inStream = inStreamSpec; 251 252 COutMemoryStream *outStreamSpec = new COutMemoryStream(dest, *destLen); 253 CMyComPtr<ISequentialOutStream> outStream = outStreamSpec; 254 255 NCompress::NLZMA::CDecoder *decoderSpec = 256 new NCompress::NLZMA::CDecoder; 257 CMyComPtr<ICompressCoder> decoder = decoderSpec; 258 259 if (decoderSpec->SetDecoderPropertiesRaw(ZLIB_LC, ZLIB_LP, ZLIB_PB, 260 (1 << 23)) != S_OK) 261 return Z_DATA_ERROR; 262 263 UInt64 fileSize = *destLen; 264 265 if (decoder->Code(inStream, outStream, 0, &fileSize, 0) != S_OK) 266 { 267 return Z_DATA_ERROR; 268 } 269 270 outStreamSpec->Seek(0, STREAM_SEEK_END, &fileSize); 271 *destLen = fileSize; 272 273 return Z_OK; 274} 275