Annotation of elwix/tools/oldlzma/SRC/7zip/Compress/LZ/BinTree/BinTreeMain.h, revision 1.1.1.1
1.1 misho 1: // BinTreeMain.h
2:
3: #include "../../../../Common/Defs.h"
4: #include "../../../../Common/CRC.h"
5: #include "../../../../Common/Alloc.h"
6:
7: namespace BT_NAMESPACE {
8:
9: #ifdef HASH_ARRAY_2
10: static const UInt32 kHash2Size = 1 << 10;
11: #ifdef HASH_ARRAY_3
12: static const UInt32 kNumHashDirectBytes = 0;
13: static const UInt32 kNumHashBytes = 4;
14: static const UInt32 kHash3Size = 1 << 18;
15: #ifdef HASH_BIG
16: static const UInt32 kHashSize = 1 << 23;
17: #else
18: static const UInt32 kHashSize = 1 << 20;
19: #endif
20: #else
21: static const UInt32 kNumHashDirectBytes = 3;
22: static const UInt32 kNumHashBytes = 3;
23: static const UInt32 kHashSize = 1 << (8 * kNumHashBytes);
24: #endif
25: #else
26: #ifdef HASH_ZIP
27: static const UInt32 kNumHashDirectBytes = 0;
28: static const UInt32 kNumHashBytes = 3;
29: static const UInt32 kHashSize = 1 << 16;
30: #else
31: #define THERE_ARE_DIRECT_HASH_BYTES
32: static const UInt32 kNumHashDirectBytes = 2;
33: static const UInt32 kNumHashBytes = 2;
34: static const UInt32 kHashSize = 1 << (8 * kNumHashBytes);
35: #endif
36: #endif
37:
38: static const UInt32 kHashSizeSum = kHashSize
39: #ifdef HASH_ARRAY_2
40: + kHash2Size
41: #ifdef HASH_ARRAY_3
42: + kHash3Size
43: #endif
44: #endif
45: ;
46:
47: #ifdef HASH_ARRAY_2
48: static const UInt32 kHash2Offset = kHashSize;
49: #ifdef HASH_ARRAY_3
50: static const UInt32 kHash3Offset = kHashSize + kHash2Size;
51: #endif
52: #endif
53:
54: CMatchFinderBinTree::CMatchFinderBinTree():
55: _hash(0),
56: _cutValue(0xFF)
57: {
58: }
59:
60: void CMatchFinderBinTree::FreeThisClassMemory()
61: {
62: BigFree(_hash);
63: _hash = 0;
64: }
65:
66: void CMatchFinderBinTree::FreeMemory()
67: {
68: FreeThisClassMemory();
69: CLZInWindow::Free();
70: }
71:
72: CMatchFinderBinTree::~CMatchFinderBinTree()
73: {
74: FreeMemory();
75: }
76:
77: STDMETHODIMP CMatchFinderBinTree::Create(UInt32 historySize, UInt32 keepAddBufferBefore,
78: UInt32 matchMaxLen, UInt32 keepAddBufferAfter)
79: {
80: UInt32 sizeReserv = (historySize + keepAddBufferBefore +
81: matchMaxLen + keepAddBufferAfter) / 2 + 256;
82: if (CLZInWindow::Create(historySize + keepAddBufferBefore,
83: matchMaxLen + keepAddBufferAfter, sizeReserv))
84: {
85: if (historySize + 256 > kMaxValForNormalize)
86: {
87: FreeMemory();
88: return E_INVALIDARG;
89: }
90: _matchMaxLen = matchMaxLen;
91: UInt32 newCyclicBufferSize = historySize + 1;
92: if (_hash != 0 && newCyclicBufferSize == _cyclicBufferSize)
93: return S_OK;
94: FreeThisClassMemory();
95: _cyclicBufferSize = newCyclicBufferSize; // don't change it
96: _hash = (CIndex *)BigAlloc((kHashSizeSum + _cyclicBufferSize * 2) * sizeof(CIndex));
97: if (_hash != 0)
98: return S_OK;
99: }
100: FreeMemory();
101: return E_OUTOFMEMORY;
102: }
103:
104: static const UInt32 kEmptyHashValue = 0;
105:
106: STDMETHODIMP CMatchFinderBinTree::Init(ISequentialInStream *stream)
107: {
108: RINOK(CLZInWindow::Init(stream));
109: for(UInt32 i = 0; i < kHashSizeSum; i++)
110: _hash[i] = kEmptyHashValue;
111: _cyclicBufferPos = 0;
112: ReduceOffsets(-1);
113: return S_OK;
114: }
115:
116: STDMETHODIMP_(void) CMatchFinderBinTree::ReleaseStream()
117: {
118: // ReleaseStream();
119: }
120:
121: #ifdef HASH_ARRAY_2
122: #ifdef HASH_ARRAY_3
123: inline UInt32 Hash(const Byte *pointer, UInt32 &hash2Value, UInt32 &hash3Value)
124: {
125: UInt32 temp = CCRC::Table[pointer[0]] ^ pointer[1];
126: hash2Value = temp & (kHash2Size - 1);
127: hash3Value = (temp ^ (UInt32(pointer[2]) << 8)) & (kHash3Size - 1);
128: return (temp ^ (UInt32(pointer[2]) << 8) ^ (CCRC::Table[pointer[3]] << 5)) &
129: (kHashSize - 1);
130: }
131: #else // no HASH_ARRAY_3
132: inline UInt32 Hash(const Byte *pointer, UInt32 &hash2Value)
133: {
134: hash2Value = (CCRC::Table[pointer[0]] ^ pointer[1]) & (kHash2Size - 1);
135: return ((UInt32(pointer[0]) << 16)) | ((UInt32(pointer[1]) << 8)) | pointer[2];
136: }
137: #endif // HASH_ARRAY_3
138: #else // no HASH_ARRAY_2
139: #ifdef HASH_ZIP
140: inline UInt32 Hash(const Byte *pointer)
141: {
142: return ((UInt32(pointer[0]) << 8) ^
143: CCRC::Table[pointer[1]] ^ pointer[2]) & (kHashSize - 1);
144: }
145: #else // no HASH_ZIP
146: inline UInt32 Hash(const Byte *pointer)
147: {
148: return pointer[0] ^ (UInt32(pointer[1]) << 8);
149: }
150: #endif // HASH_ZIP
151: #endif // HASH_ARRAY_2
152:
153: STDMETHODIMP_(UInt32) CMatchFinderBinTree::GetLongestMatch(UInt32 *distances)
154: {
155: UInt32 lenLimit;
156: if (_pos + _matchMaxLen <= _streamPos)
157: lenLimit = _matchMaxLen;
158: else
159: {
160: lenLimit = _streamPos - _pos;
161: if(lenLimit < kNumHashBytes)
162: return 0;
163: }
164:
165: UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0;
166: Byte *cur = _buffer + _pos;
167:
168: UInt32 maxLen = 0;
169:
170: #ifdef HASH_ARRAY_2
171: UInt32 hash2Value;
172: #ifdef HASH_ARRAY_3
173: UInt32 hash3Value;
174: UInt32 hashValue = Hash(cur, hash2Value, hash3Value);
175: #else
176: UInt32 hashValue = Hash(cur, hash2Value);
177: #endif
178: #else
179: UInt32 hashValue = Hash(cur);
180: #endif
181:
182: UInt32 curMatch = _hash[hashValue];
183: #ifdef HASH_ARRAY_2
184: UInt32 curMatch2 = _hash[kHash2Offset + hash2Value];
185: #ifdef HASH_ARRAY_3
186: UInt32 curMatch3 = _hash[kHash3Offset + hash3Value];
187: #endif
188: _hash[kHash2Offset + hash2Value] = _pos;
189: distances[2] = 0xFFFFFFFF;
190: if(curMatch2 > matchMinPos)
191: if (_buffer[curMatch2] == cur[0])
192: {
193: distances[2] = _pos - curMatch2 - 1;
194: maxLen = 2;
195: }
196:
197: #ifdef HASH_ARRAY_3
198: _hash[kHash3Offset + hash3Value] = _pos;
199: distances[3] = 0xFFFFFFFF;
200: if(curMatch3 > matchMinPos)
201: if (_buffer[curMatch3] == cur[0])
202: {
203: distances[3] = _pos - curMatch3 - 1;
204: maxLen = 3;
205: }
206: #endif
207: #endif
208:
209: _hash[hashValue] = _pos;
210:
211: CIndex *son = _hash + kHashSizeSum;
212: CIndex *ptr0 = son + (_cyclicBufferPos << 1) + 1;
213: CIndex *ptr1 = son + (_cyclicBufferPos << 1);
214:
215: distances[kNumHashBytes] = 0xFFFFFFFF;
216:
217: #ifdef THERE_ARE_DIRECT_HASH_BYTES
218: if (lenLimit == kNumHashDirectBytes)
219: {
220: if(curMatch > matchMinPos)
221: while (maxLen < kNumHashDirectBytes)
222: distances[++maxLen] = _pos - curMatch - 1;
223: // We don't need tree in this case
224: }
225: else
226: #endif
227: {
228: UInt32 len0, len1;
229: len0 = len1 = kNumHashDirectBytes;
230: UInt32 count = _cutValue;
231: while(true)
232: {
233: if(curMatch <= matchMinPos || count-- == 0)
234: {
235: *ptr0 = kEmptyHashValue;
236: *ptr1 = kEmptyHashValue;
237: break;
238: }
239: Byte *pb = _buffer + curMatch;
240: UInt32 len = MyMin(len0, len1);
241: do
242: {
243: if (pb[len] != cur[len])
244: break;
245: }
246: while(++len != lenLimit);
247:
248: UInt32 delta = _pos - curMatch;
249: while (maxLen < len)
250: distances[++maxLen] = delta - 1;
251:
252: UInt32 cyclicPos = (delta <= _cyclicBufferPos) ?
253: (_cyclicBufferPos - delta):
254: (_cyclicBufferPos - delta + _cyclicBufferSize);
255: CIndex *pair = son + (cyclicPos << 1);
256:
257: if (len != lenLimit)
258: {
259: if (pb[len] < cur[len])
260: {
261: *ptr1 = curMatch;
262: ptr1 = pair + 1;
263: curMatch = *ptr1;
264: len1 = len;
265: }
266: else
267: {
268: *ptr0 = curMatch;
269: ptr0 = pair;
270: curMatch = *ptr0;
271: len0 = len;
272: }
273: }
274: else
275: {
276: *ptr1 = pair[0];
277: *ptr0 = pair[1];
278: break;
279: }
280: }
281: }
282: #ifdef HASH_ARRAY_2
283: #ifdef HASH_ARRAY_3
284: if (distances[4] < distances[3])
285: distances[3] = distances[4];
286: #endif
287: if (distances[3] < distances[2])
288: distances[2] = distances[3];
289: #endif
290: return maxLen;
291: }
292:
293: STDMETHODIMP_(void) CMatchFinderBinTree::DummyLongestMatch()
294: {
295: UInt32 lenLimit;
296: if (_pos + _matchMaxLen <= _streamPos)
297: lenLimit = _matchMaxLen;
298: else
299: {
300: lenLimit = _streamPos - _pos;
301: if(lenLimit < kNumHashBytes)
302: return;
303: }
304: UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0;
305: Byte *cur = _buffer + _pos;
306:
307: #ifdef HASH_ARRAY_2
308: UInt32 hash2Value;
309: #ifdef HASH_ARRAY_3
310: UInt32 hash3Value;
311: UInt32 hashValue = Hash(cur, hash2Value, hash3Value);
312: _hash[kHash3Offset + hash3Value] = _pos;
313: #else
314: UInt32 hashValue = Hash(cur, hash2Value);
315: #endif
316: _hash[kHash2Offset + hash2Value] = _pos;
317: #else
318: UInt32 hashValue = Hash(cur);
319: #endif
320:
321: UInt32 curMatch = _hash[hashValue];
322: _hash[hashValue] = _pos;
323:
324: CIndex *son = _hash + kHashSizeSum;
325: CIndex *ptr0 = son + (_cyclicBufferPos << 1) + 1;
326: CIndex *ptr1 = son + (_cyclicBufferPos << 1);
327:
328: #ifdef THERE_ARE_DIRECT_HASH_BYTES
329: if (lenLimit != kNumHashDirectBytes)
330: #endif
331: {
332: UInt32 len0, len1;
333: len0 = len1 = kNumHashDirectBytes;
334: UInt32 count = _cutValue;
335: while(true)
336: {
337: if(curMatch <= matchMinPos || count-- == 0)
338: break;
339: Byte *pb = _buffer + curMatch;
340: UInt32 len = MyMin(len0, len1);
341: do
342: {
343: if (pb[len] != cur[len])
344: break;
345: }
346: while(++len != lenLimit);
347:
348: UInt32 delta = _pos - curMatch;
349: UInt32 cyclicPos = (delta <= _cyclicBufferPos) ?
350: (_cyclicBufferPos - delta):
351: (_cyclicBufferPos - delta + _cyclicBufferSize);
352: CIndex *pair = son + (cyclicPos << 1);
353:
354: if (len != lenLimit)
355: {
356: if (pb[len] < cur[len])
357: {
358: *ptr1 = curMatch;
359: ptr1 = pair + 1;
360: curMatch = *ptr1;
361: len1 = len;
362: }
363: else
364: {
365: *ptr0 = curMatch;
366: ptr0 = pair;
367: curMatch = *ptr0;
368: len0 = len;
369: }
370: }
371: else
372: {
373: *ptr1 = pair[0];
374: *ptr0 = pair[1];
375: return;
376: }
377: }
378: }
379: *ptr0 = kEmptyHashValue;
380: *ptr1 = kEmptyHashValue;
381: }
382:
383: void CMatchFinderBinTree::Normalize()
384: {
385: UInt32 subValue = _pos - _cyclicBufferSize;
386: CIndex *items = _hash;
387: UInt32 numItems = (kHashSizeSum + _cyclicBufferSize * 2);
388: for (UInt32 i = 0; i < numItems; i++)
389: {
390: UInt32 value = items[i];
391: if (value <= subValue)
392: value = kEmptyHashValue;
393: else
394: value -= subValue;
395: items[i] = value;
396: }
397: ReduceOffsets(subValue);
398: }
399:
400: STDMETHODIMP CMatchFinderBinTree::MovePos()
401: {
402: if (++_cyclicBufferPos == _cyclicBufferSize)
403: _cyclicBufferPos = 0;
404: RINOK(CLZInWindow::MovePos());
405: if (_pos == kMaxValForNormalize)
406: Normalize();
407: return S_OK;
408: }
409:
410: STDMETHODIMP_(Byte) CMatchFinderBinTree::GetIndexByte(Int32 index)
411: { return CLZInWindow::GetIndexByte(index); }
412:
413: STDMETHODIMP_(UInt32) CMatchFinderBinTree::GetMatchLen(Int32 index,
414: UInt32 back, UInt32 limit)
415: { return CLZInWindow::GetMatchLen(index, back, limit); }
416:
417: STDMETHODIMP_(UInt32) CMatchFinderBinTree::GetNumAvailableBytes()
418: { return CLZInWindow::GetNumAvailableBytes(); }
419:
420: STDMETHODIMP_(const Byte *) CMatchFinderBinTree::GetPointerToCurrentPos()
421: { return CLZInWindow::GetPointerToCurrentPos(); }
422:
423: // IMatchFinderSetCallback
424: STDMETHODIMP CMatchFinderBinTree::SetCallback(IMatchFinderCallback *callback)
425: {
426: m_Callback = callback;
427: return S_OK;
428: }
429:
430: void CMatchFinderBinTree::BeforeMoveBlock()
431: {
432: if (m_Callback)
433: m_Callback->BeforeChangingBufferPos();
434: CLZInWindow::BeforeMoveBlock();
435: }
436:
437: void CMatchFinderBinTree::AfterMoveBlock()
438: {
439: if (m_Callback)
440: m_Callback->AfterChangingBufferPos();
441: CLZInWindow::AfterMoveBlock();
442: }
443:
444: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>