1 // ICoder.h 2 3 #ifndef ZIP7_INC_ICODER_H 4 #define ZIP7_INC_ICODER_H 5 6 #include "IStream.h" 7 8 Z7_PURE_INTERFACES_BEGIN 9 10 #define Z7_IFACE_CONSTR_CODER(i, n) \ 11 Z7_DECL_IFACE_7ZIP(i, 4, n) \ 12 { Z7_IFACE_COM7_PURE(i) }; 13 14 #define Z7_IFACEM_ICompressProgressInfo(x) \ 15 x(SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)) 16 Z7_IFACE_CONSTR_CODER(ICompressProgressInfo, 0x04) 17 /* 18 SetRatioInfo() 19 (inSize) can be NULL, if unknown 20 (outSize) can be NULL, if unknown 21 returns: 22 S_OK 23 E_ABORT : Break by user 24 another error codes 25 */ 26 27 #define Z7_IFACEM_ICompressCoder(x) \ 28 x(Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, \ 29 const UInt64 *inSize, const UInt64 *outSize, \ 30 ICompressProgressInfo *progress)) 31 Z7_IFACE_CONSTR_CODER(ICompressCoder, 0x05) 32 33 #define Z7_IFACEM_ICompressCoder2(x) \ 34 x(Code(ISequentialInStream * const *inStreams, const UInt64 *const *inSizes, UInt32 numInStreams, \ 35 ISequentialOutStream *const *outStreams, const UInt64 *const *outSizes, UInt32 numOutStreams, \ 36 ICompressProgressInfo *progress)) 37 Z7_IFACE_CONSTR_CODER(ICompressCoder2, 0x18) 38 39 /* 40 ICompressCoder::Code 41 ICompressCoder2::Code 42 43 returns: 44 S_OK : OK 45 S_FALSE : data error (for decoders) 46 E_OUTOFMEMORY : memory allocation error 47 E_NOTIMPL : unsupported encoding method (for decoders) 48 another error code : some error. For example, it can be error code received from inStream or outStream function. 49 50 Parameters: 51 (inStream != NULL) 52 (outStream != NULL) 53 54 if (inSize != NULL) 55 { 56 Encoders in 7-Zip ignore (inSize). 57 Decoder can use (*inSize) to check that stream was decoded correctly. 58 Some decoders in 7-Zip check it, if (full_decoding mode was set via ICompressSetFinishMode) 59 } 60 61 If it's required to limit the reading from input stream (inStream), it can 62 be done with ISequentialInStream implementation. 63 64 if (outSize != NULL) 65 { 66 Encoders in 7-Zip ignore (outSize). 67 Decoder unpacks no more than (*outSize) bytes. 68 } 69 70 (progress == NULL) is allowed. 71 72 73 Decoding with Code() function 74 ----------------------------- 75 76 You can request some interfaces before decoding 77 - ICompressSetDecoderProperties2 78 - ICompressSetFinishMode 79 80 If you need to decode full stream: 81 { 82 1) try to set full_decoding mode with ICompressSetFinishMode::SetFinishMode(1); 83 2) call the Code() function with specified (inSize) and (outSize), if these sizes are known. 84 } 85 86 If you need to decode only part of stream: 87 { 88 1) try to set partial_decoding mode with ICompressSetFinishMode::SetFinishMode(0); 89 2) Call the Code() function with specified (inSize = NULL) and specified (outSize). 90 } 91 92 Encoding with Code() function 93 ----------------------------- 94 95 You can request some interfaces : 96 - ICompressSetCoderProperties - use it before encoding to set properties 97 - ICompressWriteCoderProperties - use it before or after encoding to request encoded properties. 98 99 ICompressCoder2 is used when (numInStreams != 1 || numOutStreams != 1) 100 The rules are similar to ICompressCoder rules 101 */ 102 103 104 namespace NCoderPropID 105 { 106 enum EEnum 107 { 108 kDefaultProp = 0, 109 kDictionarySize, // VT_UI4 110 kUsedMemorySize, // VT_UI4 111 kOrder, // VT_UI4 112 kBlockSize, // VT_UI4 or VT_UI8 113 kPosStateBits, // VT_UI4 114 kLitContextBits, // VT_UI4 115 kLitPosBits, // VT_UI4 116 kNumFastBytes, // VT_UI4 117 kMatchFinder, // VT_BSTR 118 kMatchFinderCycles, // VT_UI4 119 kNumPasses, // VT_UI4 120 kAlgorithm, // VT_UI4 121 kNumThreads, // VT_UI4 122 kEndMarker, // VT_BOOL 123 kLevel, // VT_UI4 124 kReduceSize, // VT_UI8 : it's estimated size of largest data stream that will be compressed 125 // encoder can use this value to reduce dictionary size and allocate data buffers 126 127 kExpectedDataSize, // VT_UI8 : for ICompressSetCoderPropertiesOpt : 128 // it's estimated size of current data stream 129 // real data size can differ from that size 130 // encoder can use this value to optimize encoder initialization 131 132 kBlockSize2, // VT_UI4 or VT_UI8 133 kCheckSize, // VT_UI4 : size of digest in bytes 134 kFilter, // VT_BSTR 135 kMemUse, // VT_UI8 136 kAffinity, // VT_UI8 137 kBranchOffset, // VT_UI4 138 kHashBits, // VT_UI4 139 /* 140 // kHash3Bits, // VT_UI4 141 // kHash2Bits, // VT_UI4 142 // kChainBits, // VT_UI4 143 kChainSize, // VT_UI4 144 kNativeLevel, // VT_UI4 145 kFast, // VT_UI4 146 kMinMatch, // VT_UI4 The minimum slen is 3 and the maximum is 7. 147 kOverlapLog, // VT_UI4 The minimum ovlog is 0 and the maximum is 9. (default: 6) 148 kRowMatchFinder, // VT_BOOL 149 kLdmEnable, // VT_BOOL 150 // kLdmWindowSizeLog, // VT_UI4 151 kLdmWindowSize, // VT_UI4 152 kLdmHashLog, // VT_UI4 The minimum ldmhlog is 6 and the maximum is 26 (default: 20). 153 kLdmMinMatchLength, // VT_UI4 The minimum ldmslen is 4 and the maximum is 4096 (default: 64). 154 kLdmBucketSizeLog, // VT_UI4 The minimum ldmblog is 0 and the maximum is 8 (default: 3). 155 kLdmHashRateLog, // VT_UI4 The default value is wlog - ldmhlog. 156 kWriteUnpackSizeFlag, // VT_BOOL 157 kUsePledged, // VT_BOOL 158 kUseSizeHintPledgedForSmall, // VT_BOOL 159 kUseSizeHintForEach, // VT_BOOL 160 kUseSizeHintGlobal, // VT_BOOL 161 kParamSelectMode, // VT_UI4 162 // kSearchLog, // VT_UI4 The minimum slog is 1 and the maximum is 26 163 // kTargetLen, // VT_UI4 The minimum tlen is 0 and the maximum is 999. 164 */ 165 k_NUM_DEFINED 166 }; 167 } 168 169 #define Z7_IFACEM_ICompressSetCoderPropertiesOpt(x) \ 170 x(SetCoderPropertiesOpt(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps)) 171 Z7_IFACE_CONSTR_CODER(ICompressSetCoderPropertiesOpt, 0x1F) 172 173 174 #define Z7_IFACEM_ICompressSetCoderProperties(x) \ 175 x(SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps)) 176 Z7_IFACE_CONSTR_CODER(ICompressSetCoderProperties, 0x20) 177 178 /* 179 #define Z7_IFACEM_ICompressSetDecoderProperties(x) \ 180 x(SetDecoderProperties(ISequentialInStream *inStream)) 181 Z7_IFACE_CONSTR_CODER(ICompressSetDecoderProperties, 0x21) 182 */ 183 184 #define Z7_IFACEM_ICompressSetDecoderProperties2(x) \ 185 x(SetDecoderProperties2(const Byte *data, UInt32 size)) 186 Z7_IFACE_CONSTR_CODER(ICompressSetDecoderProperties2, 0x22) 187 /* returns: 188 S_OK 189 E_NOTIMP : unsupported properties 190 E_INVALIDARG : incorrect (or unsupported) properties 191 E_OUTOFMEMORY : memory allocation error 192 */ 193 194 195 #define Z7_IFACEM_ICompressWriteCoderProperties(x) \ 196 x(WriteCoderProperties(ISequentialOutStream *outStream)) 197 Z7_IFACE_CONSTR_CODER(ICompressWriteCoderProperties, 0x23) 198 199 #define Z7_IFACEM_ICompressGetInStreamProcessedSize(x) \ 200 x(GetInStreamProcessedSize(UInt64 *value)) 201 Z7_IFACE_CONSTR_CODER(ICompressGetInStreamProcessedSize, 0x24) 202 203 #define Z7_IFACEM_ICompressSetCoderMt(x) \ 204 x(SetNumberOfThreads(UInt32 numThreads)) 205 Z7_IFACE_CONSTR_CODER(ICompressSetCoderMt, 0x25) 206 207 #define Z7_IFACEM_ICompressSetFinishMode(x) \ 208 x(SetFinishMode(UInt32 finishMode)) 209 Z7_IFACE_CONSTR_CODER(ICompressSetFinishMode, 0x26) 210 /* finishMode: 211 0 : partial decoding is allowed. It's default mode for ICompressCoder::Code(), if (outSize) is defined. 212 1 : full decoding. The stream must be finished at the end of decoding. */ 213 214 #define Z7_IFACEM_ICompressGetInStreamProcessedSize2(x) \ 215 x(GetInStreamProcessedSize2(UInt32 streamIndex, UInt64 *value)) 216 Z7_IFACE_CONSTR_CODER(ICompressGetInStreamProcessedSize2, 0x27) 217 218 #define Z7_IFACEM_ICompressSetMemLimit(x) \ 219 x(SetMemLimit(UInt64 memUsage)) 220 Z7_IFACE_CONSTR_CODER(ICompressSetMemLimit, 0x28) 221 222 223 /* 224 ICompressReadUnusedFromInBuf is supported by ICoder object 225 call ReadUnusedFromInBuf() after ICoder::Code(inStream, ...). 226 ICoder::Code(inStream, ...) decodes data, and the ICoder object is allowed 227 to read from inStream to internal buffers more data than minimal data required for decoding. 228 So we can call ReadUnusedFromInBuf() from same ICoder object to read unused input 229 data from the internal buffer. 230 in ReadUnusedFromInBuf(): the Coder is not allowed to use (ISequentialInStream *inStream) object, that was sent to ICoder::Code(). 231 */ 232 #define Z7_IFACEM_ICompressReadUnusedFromInBuf(x) \ 233 x(ReadUnusedFromInBuf(void *data, UInt32 size, UInt32 *processedSize)) 234 Z7_IFACE_CONSTR_CODER(ICompressReadUnusedFromInBuf, 0x29) 235 236 237 #define Z7_IFACEM_ICompressGetSubStreamSize(x) \ 238 x(GetSubStreamSize(UInt64 subStream, UInt64 *value)) 239 Z7_IFACE_CONSTR_CODER(ICompressGetSubStreamSize, 0x30) 240 /* returns: 241 S_OK : (*value) contains the size or estimated size (can be incorrect size) 242 S_FALSE : size is undefined 243 E_NOTIMP : the feature is not implemented 244 Let's (read_size) is size of data that was already read by ISequentialInStream::Read(). 245 The caller should call GetSubStreamSize() after each Read() and check sizes: 246 if (start_of_subStream + *value < read_size) 247 { 248 // (*value) is correct, and it's allowed to call GetSubStreamSize() for next subStream: 249 start_of_subStream += *value; 250 subStream++; 251 } 252 */ 253 254 #define Z7_IFACEM_ICompressSetInStream(x) \ 255 x(SetInStream(ISequentialInStream *inStream)) \ 256 x(ReleaseInStream()) 257 Z7_IFACE_CONSTR_CODER(ICompressSetInStream, 0x31) 258 259 #define Z7_IFACEM_ICompressSetOutStream(x) \ 260 x(SetOutStream(ISequentialOutStream *outStream)) \ 261 x(ReleaseOutStream()) 262 Z7_IFACE_CONSTR_CODER(ICompressSetOutStream, 0x32) 263 264 /* 265 #define Z7_IFACEM_ICompressSetInStreamSize(x) \ 266 x(SetInStreamSize(const UInt64 *inSize)) \ 267 Z7_IFACE_CONSTR_CODER(ICompressSetInStreamSize, 0x33) 268 */ 269 270 #define Z7_IFACEM_ICompressSetOutStreamSize(x) \ 271 x(SetOutStreamSize(const UInt64 *outSize)) 272 Z7_IFACE_CONSTR_CODER(ICompressSetOutStreamSize, 0x34) 273 /* That function initializes decoder structures. 274 Call this function only for stream version of decoder. 275 if (outSize == NULL), then output size is unknown 276 if (outSize != NULL), then the decoder must stop decoding after (*outSize) bytes. */ 277 278 #define Z7_IFACEM_ICompressSetBufSize(x) \ 279 x(SetInBufSize(UInt32 streamIndex, UInt32 size)) \ 280 x(SetOutBufSize(UInt32 streamIndex, UInt32 size)) 281 282 Z7_IFACE_CONSTR_CODER(ICompressSetBufSize, 0x35) 283 284 #define Z7_IFACEM_ICompressInitEncoder(x) \ 285 x(InitEncoder()) 286 Z7_IFACE_CONSTR_CODER(ICompressInitEncoder, 0x36) 287 /* That function initializes encoder structures. 288 Call this function only for stream version of encoder. */ 289 290 #define Z7_IFACEM_ICompressSetInStream2(x) \ 291 x(SetInStream2(UInt32 streamIndex, ISequentialInStream *inStream)) \ 292 x(ReleaseInStream2(UInt32 streamIndex)) 293 Z7_IFACE_CONSTR_CODER(ICompressSetInStream2, 0x37) 294 295 /* 296 #define Z7_IFACEM_ICompressSetOutStream2(x) \ 297 x(SetOutStream2(UInt32 streamIndex, ISequentialOutStream *outStream)) 298 x(ReleaseOutStream2(UInt32 streamIndex)) 299 Z7_IFACE_CONSTR_CODER(ICompressSetOutStream2, 0x38) 300 301 #define Z7_IFACEM_ICompressSetInStreamSize2(x) \ 302 x(SetInStreamSize2(UInt32 streamIndex, const UInt64 *inSize)) 303 Z7_IFACE_CONSTR_CODER(ICompressSetInStreamSize2, 0x39) 304 */ 305 306 /* 307 #define Z7_IFACEM_ICompressInSubStreams(x) \ 308 x(GetNextInSubStream(UInt64 *streamIndexRes, ISequentialInStream **stream)) 309 Z7_IFACE_CONSTR_CODER(ICompressInSubStreams, 0x3A) 310 311 #define Z7_IFACEM_ICompressOutSubStreams(x) \ 312 x(GetNextOutSubStream(UInt64 *streamIndexRes, ISequentialOutStream **stream)) 313 Z7_IFACE_CONSTR_CODER(ICompressOutSubStreams, 0x3B) 314 */ 315 316 /* 317 ICompressFilter 318 Filter(Byte *data, UInt32 size) 319 (size) 320 converts as most as possible bytes required for fast processing. 321 Some filters have (smallest_fast_block). 322 For example, (smallest_fast_block == 16) for AES CBC/CTR filters. 323 If data stream is not finished, caller must call Filter() for larger block: 324 where (size >= smallest_fast_block). 325 if (size >= smallest_fast_block) 326 { 327 The filter can leave some bytes at the end of data without conversion: 328 if there are data alignment reasons or speed reasons. 329 The caller can read additional data from stream and call Filter() again. 330 } 331 If data stream was finished, caller can call Filter() for (size < smallest_fast_block) 332 333 (data) parameter: 334 Some filters require alignment for any Filter() call: 335 1) (stream_offset % alignment_size) == (data % alignment_size) 336 2) (alignment_size == 2^N) 337 where (stream_offset) - is the number of bytes that were already filtered before. 338 The callers of Filter() are required to meet these requirements. 339 (alignment_size) can be different: 340 16 : for AES filters 341 4 or 2 : for some branch convert filters 342 1 : for another filters 343 (alignment_size >= 16) is enough for all current filters of 7-Zip. 344 But the caller can use larger (alignment_size). 345 Recommended alignment for (data) of Filter() call is (alignment_size == 64). 346 Also it's recommended to use aligned value for (size): 347 (size % alignment_size == 0), 348 if it's not last call of Filter() for current stream. 349 350 returns: (outSize): 351 if (outSize == 0) : Filter have not converted anything. 352 So the caller can stop processing, if data stream was finished. 353 if (outSize <= size) : Filter have converted outSize bytes 354 if (outSize > size) : Filter have not converted anything. 355 and it needs at least outSize bytes to convert one block 356 (it's for crypto block algorithms). 357 */ 358 359 #define Z7_IFACEM_ICompressFilter(x) \ 360 x(Init()) \ 361 x##2(UInt32, Filter(Byte *data, UInt32 size)) 362 Z7_IFACE_CONSTR_CODER(ICompressFilter, 0x40) 363 364 365 #define Z7_IFACEM_ICompressCodecsInfo(x) \ 366 x(GetNumMethods(UInt32 *numMethods)) \ 367 x(GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)) \ 368 x(CreateDecoder(UInt32 index, const GUID *iid, void* *coder)) \ 369 x(CreateEncoder(UInt32 index, const GUID *iid, void* *coder)) 370 Z7_IFACE_CONSTR_CODER(ICompressCodecsInfo, 0x60) 371 372 #define Z7_IFACEM_ISetCompressCodecsInfo(x) \ 373 x(SetCompressCodecsInfo(ICompressCodecsInfo *compressCodecsInfo)) 374 Z7_IFACE_CONSTR_CODER(ISetCompressCodecsInfo, 0x61) 375 376 #define Z7_IFACEM_ICryptoProperties(x) \ 377 x(SetKey(const Byte *data, UInt32 size)) \ 378 x(SetInitVector(const Byte *data, UInt32 size)) 379 Z7_IFACE_CONSTR_CODER(ICryptoProperties, 0x80) 380 381 /* 382 x(ResetSalt()) 383 Z7_IFACE_CONSTR_CODER(ICryptoResetSalt, 0x88) 384 */ 385 386 #define Z7_IFACEM_ICryptoResetInitVector(x) \ 387 x(ResetInitVector()) 388 Z7_IFACE_CONSTR_CODER(ICryptoResetInitVector, 0x8C) 389 /* Call ResetInitVector() only for encoding. 390 Call ResetInitVector() before encoding and before WriteCoderProperties(). 391 Crypto encoder can create random IV in that function. */ 392 393 #define Z7_IFACEM_ICryptoSetPassword(x) \ 394 x(CryptoSetPassword(const Byte *data, UInt32 size)) 395 Z7_IFACE_CONSTR_CODER(ICryptoSetPassword, 0x90) 396 397 #define Z7_IFACEM_ICryptoSetCRC(x) \ 398 x(CryptoSetCRC(UInt32 crc)) 399 Z7_IFACE_CONSTR_CODER(ICryptoSetCRC, 0xA0) 400 401 402 namespace NMethodPropID 403 { 404 enum EEnum 405 { 406 kID, 407 kName, 408 kDecoder, 409 kEncoder, 410 kPackStreams, 411 kUnpackStreams, 412 kDescription, 413 kDecoderIsAssigned, 414 kEncoderIsAssigned, 415 kDigestSize, 416 kIsFilter 417 }; 418 } 419 420 namespace NModuleInterfaceType 421 { 422 /* 423 virtual destructor in IUnknown: 424 - no : 7-Zip (Windows) 425 - no : 7-Zip (Linux) (v23) in default mode 426 - yes : p7zip 427 - yes : 7-Zip (Linux) before v23 428 - yes : 7-Zip (Linux) (v23), if Z7_USE_VIRTUAL_DESTRUCTOR_IN_IUNKNOWN is defined 429 */ 430 const UInt32 k_IUnknown_VirtDestructor_No = 0; 431 const UInt32 k_IUnknown_VirtDestructor_Yes = 1; 432 const UInt32 k_IUnknown_VirtDestructor_ThisModule = 433 #if !defined(_WIN32) && defined(Z7_USE_VIRTUAL_DESTRUCTOR_IN_IUNKNOWN) 434 k_IUnknown_VirtDestructor_Yes; 435 #else 436 k_IUnknown_VirtDestructor_No; 437 #endif 438 } 439 440 namespace NModulePropID 441 { 442 enum EEnum 443 { 444 kInterfaceType, // VT_UI4 445 kVersion // VT_UI4 446 }; 447 } 448 449 450 #define Z7_IFACEM_IHasher(x) \ 451 x##2(void, Init()) \ 452 x##2(void, Update(const void *data, UInt32 size)) \ 453 x##2(void, Final(Byte *digest)) \ 454 x##2(UInt32, GetDigestSize()) 455 Z7_IFACE_CONSTR_CODER(IHasher, 0xC0) 456 457 #define Z7_IFACEM_IHashers(x) \ 458 x##2(UInt32, GetNumHashers()) \ 459 x(GetHasherProp(UInt32 index, PROPID propID, PROPVARIANT *value)) \ 460 x(CreateHasher(UInt32 index, IHasher **hasher)) 461 Z7_IFACE_CONSTR_CODER(IHashers, 0xC1) 462 463 extern "C" 464 { 465 typedef HRESULT (WINAPI *Func_GetNumberOfMethods)(UInt32 *numMethods); 466 typedef HRESULT (WINAPI *Func_GetMethodProperty)(UInt32 index, PROPID propID, PROPVARIANT *value); 467 typedef HRESULT (WINAPI *Func_CreateDecoder)(UInt32 index, const GUID *iid, void **outObject); 468 typedef HRESULT (WINAPI *Func_CreateEncoder)(UInt32 index, const GUID *iid, void **outObject); 469 470 typedef HRESULT (WINAPI *Func_GetHashers)(IHashers **hashers); 471 472 typedef HRESULT (WINAPI *Func_SetCodecs)(ICompressCodecsInfo *compressCodecsInfo); 473 typedef HRESULT (WINAPI *Func_GetModuleProp)(PROPID propID, PROPVARIANT *value); 474 } 475 476 Z7_PURE_INTERFACES_END 477 #endif 478