pylzma_encoder.cpp 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. /*
  2. * Python Bindings for LZMA
  3. *
  4. * Copyright (c) 2004-2006 by Joachim Bauch, mail@joachim-bauch.de
  5. * 7-Zip Copyright (C) 1999-2005 Igor Pavlov
  6. * LZMA SDK Copyright (C) 1999-2005 Igor Pavlov
  7. *
  8. * This library is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU Lesser General Public
  10. * License as published by the Free Software Foundation; either
  11. * version 2.1 of the License, or (at your option) any later version.
  12. *
  13. * This library is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. * Lesser General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with this library; if not, write to the Free Software
  20. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  21. *
  22. * $Id: pylzma_encoder.cpp 104 2006-01-08 18:17:14Z jojo $
  23. *
  24. */
  25. #include <stdio.h>
  26. #include "Platform.h"
  27. #include "pylzma_encoder.h"
  28. #include <7zip/7zip/Compress/LZMA/LZMAEncoder.h>
  29. #include <7zip/7zip/Compress/LZ/LZInWindow.h>
  30. namespace NCompress {
  31. namespace NLZMA {
  32. HRESULT CPYLZMAEncoder::CodeOneBlock(UINT64 *inSize, UINT64 *outSize, INT32 *finished, bool flush)
  33. {
  34. if (_inStream != 0)
  35. {
  36. RINOK(_matchFinder->Init(_inStream));
  37. _inStream = 0;
  38. state = 0;
  39. }
  40. *finished = 1;
  41. if (state > 0 && state < 4)
  42. _matchFinder->ResetStreamEndReached();
  43. switch (state)
  44. {
  45. case 0: goto state0;
  46. case 1: goto state1;
  47. case 2: goto state2;
  48. case 3: goto state3;
  49. case 4: goto state4;
  50. }
  51. state0:
  52. if (_finished)
  53. {
  54. return S_OK;
  55. }
  56. _finished = true;
  57. progressPosValuePrev = nowPos64;
  58. if (nowPos64 == 0)
  59. {
  60. state1:
  61. if (_matchFinder->GetNumAvailableBytes() == 0)
  62. {
  63. state = 1;
  64. return S_OK;
  65. }
  66. ReadMatchDistances();
  67. UINT32 posState = UINT32(nowPos64) & _posStateMask;
  68. _mainChoiceEncoders[_state.Index][posState].Encode(&_rangeEncoder, kMainChoiceLiteralIndex);
  69. _state.UpdateChar();
  70. BYTE curByte = _matchFinder->GetIndexByte(0 - _additionalOffset);
  71. _literalEncoder.Encode(&_rangeEncoder, UINT32(nowPos64), _previousByte,
  72. false, 0, curByte);
  73. _previousByte = curByte;
  74. _additionalOffset--;
  75. nowPos64++;
  76. }
  77. state2:
  78. if (_matchFinder->GetNumAvailableBytes() == 0)
  79. {
  80. state = 2;
  81. return S_OK;
  82. }
  83. while(true)
  84. {
  85. state4:
  86. posState = UINT32(nowPos64) & _posStateMask;
  87. if (_fastMode)
  88. len = GetOptimumFast(pos, UINT32(nowPos64));
  89. else
  90. len = GetOptimum(pos, UINT32(nowPos64));
  91. if(len == 1 && pos == (UINT32)(-1))
  92. {
  93. _mainChoiceEncoders[_state.Index][posState].Encode(&_rangeEncoder, kMainChoiceLiteralIndex);
  94. _state.UpdateChar();
  95. BYTE matchByte = 0;
  96. if(_peviousIsMatch)
  97. matchByte = _matchFinder->GetIndexByte(0 - _repDistances[0] - 1 - _additionalOffset);
  98. BYTE curByte = _matchFinder->GetIndexByte(0 - _additionalOffset);
  99. _literalEncoder.Encode(&_rangeEncoder, UINT32(nowPos64), _previousByte, _peviousIsMatch,
  100. matchByte, curByte);
  101. _previousByte = curByte;
  102. _peviousIsMatch = false;
  103. }
  104. else
  105. {
  106. _peviousIsMatch = true;
  107. _mainChoiceEncoders[_state.Index][posState].Encode(&_rangeEncoder, kMainChoiceMatchIndex);
  108. if(pos < kNumRepDistances)
  109. {
  110. _matchChoiceEncoders[_state.Index].Encode(&_rangeEncoder, kMatchChoiceRepetitionIndex);
  111. if(pos == 0)
  112. {
  113. _matchRepChoiceEncoders[_state.Index].Encode(&_rangeEncoder, 0);
  114. if(len == 1)
  115. _matchRepShortChoiceEncoders[_state.Index][posState].Encode(&_rangeEncoder, 0);
  116. else
  117. _matchRepShortChoiceEncoders[_state.Index][posState].Encode(&_rangeEncoder, 1);
  118. }
  119. else
  120. {
  121. _matchRepChoiceEncoders[_state.Index].Encode(&_rangeEncoder, 1);
  122. if (pos == 1)
  123. _matchRep1ChoiceEncoders[_state.Index].Encode(&_rangeEncoder, 0);
  124. else
  125. {
  126. _matchRep1ChoiceEncoders[_state.Index].Encode(&_rangeEncoder, 1);
  127. _matchRep2ChoiceEncoders[_state.Index].Encode(&_rangeEncoder, pos - 2);
  128. }
  129. }
  130. if (len == 1)
  131. _state.UpdateShortRep();
  132. else
  133. {
  134. _repMatchLenEncoder.Encode(&_rangeEncoder, len - kMatchMinLen, posState);
  135. _state.UpdateRep();
  136. }
  137. UINT32 distance = _repDistances[pos];
  138. if (pos != 0)
  139. {
  140. for(UINT32 i = pos; i >= 1; i--)
  141. _repDistances[i] = _repDistances[i - 1];
  142. _repDistances[0] = distance;
  143. }
  144. }
  145. else
  146. {
  147. _matchChoiceEncoders[_state.Index].Encode(&_rangeEncoder, kMatchChoiceDistanceIndex);
  148. _state.UpdateMatch();
  149. _lenEncoder.Encode(&_rangeEncoder, len - kMatchMinLen, posState);
  150. pos -= kNumRepDistances;
  151. UINT32 posSlot = GetPosSlot(pos);
  152. UINT32 lenToPosState = GetLenToPosState(len);
  153. _posSlotEncoder[lenToPosState].Encode(&_rangeEncoder, posSlot);
  154. if (posSlot >= kStartPosModelIndex)
  155. {
  156. UINT32 footerBits = ((posSlot >> 1) - 1);
  157. UINT32 posReduced = pos - ((2 | (posSlot & 1)) << footerBits);
  158. if (posSlot < kEndPosModelIndex)
  159. _posEncoders[posSlot - kStartPosModelIndex].Encode(&_rangeEncoder, posReduced);
  160. else
  161. {
  162. _rangeEncoder.EncodeDirectBits(posReduced >> kNumAlignBits, footerBits - kNumAlignBits);
  163. _posAlignEncoder.Encode(&_rangeEncoder, posReduced & kAlignMask);
  164. if (!_fastMode)
  165. if (--_alignPriceCount == 0)
  166. FillAlignPrices();
  167. }
  168. }
  169. UINT32 distance = pos;
  170. for(UINT32 i = kNumRepDistances - 1; i >= 1; i--)
  171. _repDistances[i] = _repDistances[i - 1];
  172. _repDistances[0] = distance;
  173. }
  174. _previousByte = _matchFinder->GetIndexByte(len - 1 - _additionalOffset);
  175. }
  176. _additionalOffset -= len;
  177. nowPos64 += len;
  178. if (!_fastMode)
  179. if (nowPos64 - lastPosSlotFillingPos >= (1 << 9))
  180. {
  181. FillPosSlotPrices();
  182. FillDistancesPrices();
  183. lastPosSlotFillingPos = nowPos64;
  184. }
  185. if (_additionalOffset == 0)
  186. {
  187. *inSize = nowPos64;
  188. *outSize = _rangeEncoder.GetProcessedSize();
  189. state3:
  190. if (_matchFinder->GetNumAvailableBytes() == 0)
  191. {
  192. state = 3;
  193. return S_OK;
  194. }
  195. if (nowPos64 - progressPosValuePrev >= (1 << 12))
  196. {
  197. _finished = false;
  198. *finished = 0;
  199. state = 0;
  200. return S_OK;
  201. }
  202. }
  203. state = 4;
  204. }
  205. }
  206. HRESULT CPYLZMAEncoder::FinishStream()
  207. {
  208. _finished = true;
  209. _matchFinder->ReleaseStream();
  210. WriteEndMarker(UINT32(nowPos64) & _posStateMask);
  211. return Flush();
  212. }
  213. }}