LzmaRam.cpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. // LzmaRam.cpp
  2. #include "StdAfx.h"
  3. #include "../../../Common/Types.h"
  4. #include "../LZMA/LZMADecoder.h"
  5. #include "../LZMA/LZMAEncoder.h"
  6. #include "LzmaRam.h"
  7. extern "C"
  8. {
  9. #include "../../../../C/Compress/Branch/BranchX86.h"
  10. }
  11. class CInStreamRam:
  12. public ISequentialInStream,
  13. public CMyUnknownImp
  14. {
  15. const Byte *Data;
  16. size_t Size;
  17. size_t Pos;
  18. public:
  19. MY_UNKNOWN_IMP
  20. void Init(const Byte *data, size_t size)
  21. {
  22. Data = data;
  23. Size = size;
  24. Pos = 0;
  25. }
  26. STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
  27. };
  28. STDMETHODIMP CInStreamRam::Read(void *data, UInt32 size, UInt32 *processedSize)
  29. {
  30. if (size > (Size - Pos))
  31. size = (UInt32)(Size - Pos);
  32. for (UInt32 i = 0; i < size; i++)
  33. ((Byte *)data)[i] = Data[Pos + i];
  34. Pos += size;
  35. if(processedSize != NULL)
  36. *processedSize = size;
  37. return S_OK;
  38. }
  39. class COutStreamRam:
  40. public ISequentialOutStream,
  41. public CMyUnknownImp
  42. {
  43. size_t Size;
  44. public:
  45. Byte *Data;
  46. size_t Pos;
  47. bool Overflow;
  48. void Init(Byte *data, size_t size)
  49. {
  50. Data = data;
  51. Size = size;
  52. Pos = 0;
  53. Overflow = false;
  54. }
  55. void SetPos(size_t pos)
  56. {
  57. Overflow = false;
  58. Pos = pos;
  59. }
  60. MY_UNKNOWN_IMP
  61. HRESULT WriteByte(Byte b)
  62. {
  63. if (Pos >= Size)
  64. {
  65. Overflow = true;
  66. return E_FAIL;
  67. }
  68. Data[Pos++] = b;
  69. return S_OK;
  70. }
  71. STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
  72. };
  73. STDMETHODIMP COutStreamRam::Write(const void *data, UInt32 size, UInt32 *processedSize)
  74. {
  75. UInt32 i;
  76. for (i = 0; i < size && Pos < Size; i++)
  77. Data[Pos++] = ((const Byte *)data)[i];
  78. if(processedSize != NULL)
  79. *processedSize = i;
  80. if (i != size)
  81. {
  82. Overflow = true;
  83. return E_FAIL;
  84. }
  85. return S_OK;
  86. }
  87. #define SZ_RAM_E_FAIL (1)
  88. #define SZ_RAM_E_OUTOFMEMORY (2)
  89. #define SZE_OUT_OVERFLOW (3)
  90. int LzmaRamEncode(
  91. const Byte *inBuffer, size_t inSize,
  92. Byte *outBuffer, size_t outSize, size_t *outSizeProcessed,
  93. UInt32 dictionarySize, ESzFilterMode filterMode)
  94. {
  95. #ifndef _NO_EXCEPTIONS
  96. try {
  97. #endif
  98. *outSizeProcessed = 0;
  99. const size_t kIdSize = 1;
  100. const size_t kLzmaPropsSize = 5;
  101. const size_t kMinDestSize = kIdSize + kLzmaPropsSize + 8;
  102. if (outSize < kMinDestSize)
  103. return SZE_OUT_OVERFLOW;
  104. NCompress::NLZMA::CEncoder *encoderSpec = new NCompress::NLZMA::CEncoder;
  105. CMyComPtr<ICompressCoder> encoder = encoderSpec;
  106. PROPID propIDs[] =
  107. {
  108. NCoderPropID::kAlgorithm,
  109. NCoderPropID::kDictionarySize,
  110. NCoderPropID::kNumFastBytes,
  111. };
  112. const int kNumProps = sizeof(propIDs) / sizeof(propIDs[0]);
  113. PROPVARIANT properties[kNumProps];
  114. properties[0].vt = VT_UI4;
  115. properties[1].vt = VT_UI4;
  116. properties[2].vt = VT_UI4;
  117. properties[0].ulVal = (UInt32)2;
  118. properties[1].ulVal = (UInt32)dictionarySize;
  119. properties[2].ulVal = (UInt32)64;
  120. if (encoderSpec->SetCoderProperties(propIDs, properties, kNumProps) != S_OK)
  121. return 1;
  122. COutStreamRam *outStreamSpec = new COutStreamRam;
  123. if (outStreamSpec == 0)
  124. return SZ_RAM_E_OUTOFMEMORY;
  125. CMyComPtr<ISequentialOutStream> outStream = outStreamSpec;
  126. CInStreamRam *inStreamSpec = new CInStreamRam;
  127. if (inStreamSpec == 0)
  128. return SZ_RAM_E_OUTOFMEMORY;
  129. CMyComPtr<ISequentialInStream> inStream = inStreamSpec;
  130. outStreamSpec->Init(outBuffer, outSize);
  131. if (outStreamSpec->WriteByte(0) != S_OK)
  132. return SZE_OUT_OVERFLOW;
  133. if (encoderSpec->WriteCoderProperties(outStream) != S_OK)
  134. return SZE_OUT_OVERFLOW;
  135. if (outStreamSpec->Pos != kIdSize + kLzmaPropsSize)
  136. return 1;
  137. int i;
  138. for (i = 0; i < 8; i++)
  139. {
  140. UInt64 t = (UInt64)(inSize);
  141. if (outStreamSpec->WriteByte((Byte)((t) >> (8 * i))) != S_OK)
  142. return SZE_OUT_OVERFLOW;
  143. }
  144. Byte *filteredStream = 0;
  145. bool useFilter = (filterMode != SZ_FILTER_NO);
  146. if (useFilter)
  147. {
  148. if (inSize != 0)
  149. {
  150. filteredStream = (Byte *)MyAlloc(inSize);
  151. if (filteredStream == 0)
  152. return SZ_RAM_E_OUTOFMEMORY;
  153. memmove(filteredStream, inBuffer, inSize);
  154. }
  155. UInt32 x86State;
  156. x86_Convert_Init(x86State);
  157. x86_Convert(filteredStream, (SizeT)inSize, 0, &x86State, 1);
  158. }
  159. size_t minSize = 0;
  160. int numPasses = (filterMode == SZ_FILTER_AUTO) ? 3 : 1;
  161. bool bestIsFiltered = false;
  162. int mainResult = 0;
  163. size_t startPos = outStreamSpec->Pos;
  164. for (i = 0; i < numPasses; i++)
  165. {
  166. if (numPasses > 1 && i == numPasses - 1 && !bestIsFiltered)
  167. break;
  168. outStreamSpec->SetPos(startPos);
  169. bool curModeIsFiltered = false;
  170. if (useFilter && i == 0)
  171. curModeIsFiltered = true;
  172. if (numPasses > 1 && i == numPasses - 1)
  173. curModeIsFiltered = true;
  174. inStreamSpec->Init(curModeIsFiltered ? filteredStream : inBuffer, inSize);
  175. HRESULT lzmaResult = encoder->Code(inStream, outStream, 0, 0, 0);
  176. mainResult = 0;
  177. if (lzmaResult == E_OUTOFMEMORY)
  178. {
  179. mainResult = SZ_RAM_E_OUTOFMEMORY;
  180. break;
  181. }
  182. if (i == 0 || outStreamSpec->Pos <= minSize)
  183. {
  184. minSize = outStreamSpec->Pos;
  185. bestIsFiltered = curModeIsFiltered;
  186. }
  187. if (outStreamSpec->Overflow)
  188. mainResult = SZE_OUT_OVERFLOW;
  189. else if (lzmaResult != S_OK)
  190. {
  191. mainResult = SZ_RAM_E_FAIL;
  192. break;
  193. }
  194. }
  195. *outSizeProcessed = outStreamSpec->Pos;
  196. if (bestIsFiltered)
  197. outBuffer[0] = 1;
  198. if (useFilter)
  199. MyFree(filteredStream);
  200. return mainResult;
  201. #ifndef _NO_EXCEPTIONS
  202. } catch(...) { return SZ_RAM_E_OUTOFMEMORY; }
  203. #endif
  204. }