2
0

BinTree.java 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  1. // LZ.BinTree
  2. package SevenZip.Compression.LZ;
  3. import java.io.IOException;
  4. public class BinTree extends InWindow
  5. {
  6. int _cyclicBufferPos;
  7. int _cyclicBufferSize = 0;
  8. int _matchMaxLen;
  9. int[] _son;
  10. int[] _hash;
  11. int _cutValue = 0xFF;
  12. int _hashMask;
  13. int _hashSizeSum = 0;
  14. boolean HASH_ARRAY = true;
  15. static final int kHash2Size = 1 << 10;
  16. static final int kHash3Size = 1 << 16;
  17. static final int kBT2HashSize = 1 << 16;
  18. static final int kStartMaxLen = 1;
  19. static final int kHash3Offset = kHash2Size;
  20. static final int kEmptyHashValue = 0;
  21. static final int kMaxValForNormalize = (1 << 30) - 1;
  22. int kNumHashDirectBytes = 0;
  23. int kMinMatchCheck = 4;
  24. int kFixHashSize = kHash2Size + kHash3Size;
  25. public void SetType(int numHashBytes)
  26. {
  27. HASH_ARRAY = (numHashBytes > 2);
  28. if (HASH_ARRAY)
  29. {
  30. kNumHashDirectBytes = 0;
  31. kMinMatchCheck = 4;
  32. kFixHashSize = kHash2Size + kHash3Size;
  33. }
  34. else
  35. {
  36. kNumHashDirectBytes = 2;
  37. kMinMatchCheck = 2 + 1;
  38. kFixHashSize = 0;
  39. }
  40. }
  41. public void Init() throws IOException
  42. {
  43. super.Init();
  44. for (int i = 0; i < _hashSizeSum; i++)
  45. _hash[i] = kEmptyHashValue;
  46. _cyclicBufferPos = 0;
  47. ReduceOffsets(-1);
  48. }
  49. public void MovePos() throws IOException
  50. {
  51. if (++_cyclicBufferPos >= _cyclicBufferSize)
  52. _cyclicBufferPos = 0;
  53. super.MovePos();
  54. if (_pos == kMaxValForNormalize)
  55. Normalize();
  56. }
  57. public boolean Create(int historySize, int keepAddBufferBefore,
  58. int matchMaxLen, int keepAddBufferAfter)
  59. {
  60. if (historySize > kMaxValForNormalize - 256)
  61. return false;
  62. _cutValue = 16 + (matchMaxLen >> 1);
  63. int windowReservSize = (historySize + keepAddBufferBefore +
  64. matchMaxLen + keepAddBufferAfter) / 2 + 256;
  65. super.Create(historySize + keepAddBufferBefore, matchMaxLen + keepAddBufferAfter, windowReservSize);
  66. _matchMaxLen = matchMaxLen;
  67. int cyclicBufferSize = historySize + 1;
  68. if (_cyclicBufferSize != cyclicBufferSize)
  69. _son = new int[(_cyclicBufferSize = cyclicBufferSize) * 2];
  70. int hs = kBT2HashSize;
  71. if (HASH_ARRAY)
  72. {
  73. hs = historySize - 1;
  74. hs |= (hs >> 1);
  75. hs |= (hs >> 2);
  76. hs |= (hs >> 4);
  77. hs |= (hs >> 8);
  78. hs >>= 1;
  79. hs |= 0xFFFF;
  80. if (hs > (1 << 24))
  81. hs >>= 1;
  82. _hashMask = hs;
  83. hs++;
  84. hs += kFixHashSize;
  85. }
  86. if (hs != _hashSizeSum)
  87. _hash = new int [_hashSizeSum = hs];
  88. return true;
  89. }
  90. public int GetMatches(int[] distances) throws IOException
  91. {
  92. int lenLimit;
  93. if (_pos + _matchMaxLen <= _streamPos)
  94. lenLimit = _matchMaxLen;
  95. else
  96. {
  97. lenLimit = _streamPos - _pos;
  98. if (lenLimit < kMinMatchCheck)
  99. {
  100. MovePos();
  101. return 0;
  102. }
  103. }
  104. int offset = 0;
  105. int matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0;
  106. int cur = _bufferOffset + _pos;
  107. int maxLen = kStartMaxLen; // to avoid items for len < hashSize;
  108. int hashValue, hash2Value = 0, hash3Value = 0;
  109. if (HASH_ARRAY)
  110. {
  111. int temp = CrcTable[_bufferBase[cur] & 0xFF] ^ (_bufferBase[cur + 1] & 0xFF);
  112. hash2Value = temp & (kHash2Size - 1);
  113. temp ^= ((int)(_bufferBase[cur + 2] & 0xFF) << 8);
  114. hash3Value = temp & (kHash3Size - 1);
  115. hashValue = (temp ^ (CrcTable[_bufferBase[cur + 3] & 0xFF] << 5)) & _hashMask;
  116. }
  117. else
  118. hashValue = ((_bufferBase[cur] & 0xFF) ^ ((int)(_bufferBase[cur + 1] & 0xFF) << 8));
  119. int curMatch = _hash[kFixHashSize + hashValue];
  120. if (HASH_ARRAY)
  121. {
  122. int curMatch2 = _hash[hash2Value];
  123. int curMatch3 = _hash[kHash3Offset + hash3Value];
  124. _hash[hash2Value] = _pos;
  125. _hash[kHash3Offset + hash3Value] = _pos;
  126. if (curMatch2 > matchMinPos)
  127. if (_bufferBase[_bufferOffset + curMatch2] == _bufferBase[cur])
  128. {
  129. distances[offset++] = maxLen = 2;
  130. distances[offset++] = _pos - curMatch2 - 1;
  131. }
  132. if (curMatch3 > matchMinPos)
  133. if (_bufferBase[_bufferOffset + curMatch3] == _bufferBase[cur])
  134. {
  135. if (curMatch3 == curMatch2)
  136. offset -= 2;
  137. distances[offset++] = maxLen = 3;
  138. distances[offset++] = _pos - curMatch3 - 1;
  139. curMatch2 = curMatch3;
  140. }
  141. if (offset != 0 && curMatch2 == curMatch)
  142. {
  143. offset -= 2;
  144. maxLen = kStartMaxLen;
  145. }
  146. }
  147. _hash[kFixHashSize + hashValue] = _pos;
  148. int ptr0 = (_cyclicBufferPos << 1) + 1;
  149. int ptr1 = (_cyclicBufferPos << 1);
  150. int len0, len1;
  151. len0 = len1 = kNumHashDirectBytes;
  152. if (kNumHashDirectBytes != 0)
  153. {
  154. if (curMatch > matchMinPos)
  155. {
  156. if (_bufferBase[_bufferOffset + curMatch + kNumHashDirectBytes] !=
  157. _bufferBase[cur + kNumHashDirectBytes])
  158. {
  159. distances[offset++] = maxLen = kNumHashDirectBytes;
  160. distances[offset++] = _pos - curMatch - 1;
  161. }
  162. }
  163. }
  164. int count = _cutValue;
  165. while (true)
  166. {
  167. if (curMatch <= matchMinPos || count-- == 0)
  168. {
  169. _son[ptr0] = _son[ptr1] = kEmptyHashValue;
  170. break;
  171. }
  172. int delta = _pos - curMatch;
  173. int cyclicPos = ((delta <= _cyclicBufferPos) ?
  174. (_cyclicBufferPos - delta) :
  175. (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1;
  176. int pby1 = _bufferOffset + curMatch;
  177. int len = Math.min(len0, len1);
  178. if (_bufferBase[pby1 + len] == _bufferBase[cur + len])
  179. {
  180. while(++len != lenLimit)
  181. if (_bufferBase[pby1 + len] != _bufferBase[cur + len])
  182. break;
  183. if (maxLen < len)
  184. {
  185. distances[offset++] = maxLen = len;
  186. distances[offset++] = delta - 1;
  187. if (len == lenLimit)
  188. {
  189. _son[ptr1] = _son[cyclicPos];
  190. _son[ptr0] = _son[cyclicPos + 1];
  191. break;
  192. }
  193. }
  194. }
  195. if ((_bufferBase[pby1 + len] & 0xFF) < (_bufferBase[cur + len] & 0xFF))
  196. {
  197. _son[ptr1] = curMatch;
  198. ptr1 = cyclicPos + 1;
  199. curMatch = _son[ptr1];
  200. len1 = len;
  201. }
  202. else
  203. {
  204. _son[ptr0] = curMatch;
  205. ptr0 = cyclicPos;
  206. curMatch = _son[ptr0];
  207. len0 = len;
  208. }
  209. }
  210. MovePos();
  211. return offset;
  212. }
  213. public void Skip(int num) throws IOException
  214. {
  215. do
  216. {
  217. int lenLimit;
  218. if (_pos + _matchMaxLen <= _streamPos)
  219. lenLimit = _matchMaxLen;
  220. else
  221. {
  222. lenLimit = _streamPos - _pos;
  223. if (lenLimit < kMinMatchCheck)
  224. {
  225. MovePos();
  226. continue;
  227. }
  228. }
  229. int matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0;
  230. int cur = _bufferOffset + _pos;
  231. int hashValue;
  232. if (HASH_ARRAY)
  233. {
  234. int temp = CrcTable[_bufferBase[cur] & 0xFF] ^ (_bufferBase[cur + 1] & 0xFF);
  235. int hash2Value = temp & (kHash2Size - 1);
  236. _hash[hash2Value] = _pos;
  237. temp ^= ((int)(_bufferBase[cur + 2] & 0xFF) << 8);
  238. int hash3Value = temp & (kHash3Size - 1);
  239. _hash[kHash3Offset + hash3Value] = _pos;
  240. hashValue = (temp ^ (CrcTable[_bufferBase[cur + 3] & 0xFF] << 5)) & _hashMask;
  241. }
  242. else
  243. hashValue = ((_bufferBase[cur] & 0xFF) ^ ((int)(_bufferBase[cur + 1] & 0xFF) << 8));
  244. int curMatch = _hash[kFixHashSize + hashValue];
  245. _hash[kFixHashSize + hashValue] = _pos;
  246. int ptr0 = (_cyclicBufferPos << 1) + 1;
  247. int ptr1 = (_cyclicBufferPos << 1);
  248. int len0, len1;
  249. len0 = len1 = kNumHashDirectBytes;
  250. int count = _cutValue;
  251. while (true)
  252. {
  253. if (curMatch <= matchMinPos || count-- == 0)
  254. {
  255. _son[ptr0] = _son[ptr1] = kEmptyHashValue;
  256. break;
  257. }
  258. int delta = _pos - curMatch;
  259. int cyclicPos = ((delta <= _cyclicBufferPos) ?
  260. (_cyclicBufferPos - delta) :
  261. (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1;
  262. int pby1 = _bufferOffset + curMatch;
  263. int len = Math.min(len0, len1);
  264. if (_bufferBase[pby1 + len] == _bufferBase[cur + len])
  265. {
  266. while (++len != lenLimit)
  267. if (_bufferBase[pby1 + len] != _bufferBase[cur + len])
  268. break;
  269. if (len == lenLimit)
  270. {
  271. _son[ptr1] = _son[cyclicPos];
  272. _son[ptr0] = _son[cyclicPos + 1];
  273. break;
  274. }
  275. }
  276. if ((_bufferBase[pby1 + len] & 0xFF) < (_bufferBase[cur + len] & 0xFF))
  277. {
  278. _son[ptr1] = curMatch;
  279. ptr1 = cyclicPos + 1;
  280. curMatch = _son[ptr1];
  281. len1 = len;
  282. }
  283. else
  284. {
  285. _son[ptr0] = curMatch;
  286. ptr0 = cyclicPos;
  287. curMatch = _son[ptr0];
  288. len0 = len;
  289. }
  290. }
  291. MovePos();
  292. }
  293. while (--num != 0);
  294. }
  295. void NormalizeLinks(int[] items, int numItems, int subValue)
  296. {
  297. for (int i = 0; i < numItems; i++)
  298. {
  299. int value = items[i];
  300. if (value <= subValue)
  301. value = kEmptyHashValue;
  302. else
  303. value -= subValue;
  304. items[i] = value;
  305. }
  306. }
  307. void Normalize()
  308. {
  309. int subValue = _pos - _cyclicBufferSize;
  310. NormalizeLinks(_son, _cyclicBufferSize * 2, subValue);
  311. NormalizeLinks(_hash, _hashSizeSum, subValue);
  312. ReduceOffsets(subValue);
  313. }
  314. public void SetCutValue(int cutValue) { _cutValue = cutValue; }
  315. private static final int[] CrcTable = new int[256];
  316. static
  317. {
  318. for (int i = 0; i < 256; i++)
  319. {
  320. int r = i;
  321. for (int j = 0; j < 8; j++)
  322. if ((r & 1) != 0)
  323. r = (r >>> 1) ^ 0xEDB88320;
  324. else
  325. r >>>= 1;
  326. CrcTable[i] = r;
  327. }
  328. }
  329. }