ruby-lzma 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. data/.gitignore +6 -0
  2. data/README.markdown +15 -0
  3. data/Rakefile +53 -0
  4. data/VERSION +1 -0
  5. data/ext/Alloc.cpp +118 -0
  6. data/ext/Alloc.h +29 -0
  7. data/ext/BinTree.h +55 -0
  8. data/ext/BinTree2.h +12 -0
  9. data/ext/BinTree3.h +16 -0
  10. data/ext/BinTree3Z.h +16 -0
  11. data/ext/BinTree4.h +18 -0
  12. data/ext/BinTree4b.h +20 -0
  13. data/ext/BinTreeMain.h +444 -0
  14. data/ext/BranchX86.c +101 -0
  15. data/ext/BranchX86.h +19 -0
  16. data/ext/CRC.cpp +61 -0
  17. data/ext/CRC.h +36 -0
  18. data/ext/C_FileIO.h +45 -0
  19. data/ext/CommandLineParser.h +82 -0
  20. data/ext/Defs.h +20 -0
  21. data/ext/FileStreams.h +98 -0
  22. data/ext/HC.h +55 -0
  23. data/ext/HC2.h +13 -0
  24. data/ext/HC3.h +17 -0
  25. data/ext/HC4.h +19 -0
  26. data/ext/HC4b.h +21 -0
  27. data/ext/HCMain.h +350 -0
  28. data/ext/ICoder.h +156 -0
  29. data/ext/IMatchFinder.h +63 -0
  30. data/ext/IStream.h +62 -0
  31. data/ext/InBuffer.cpp +80 -0
  32. data/ext/InBuffer.h +76 -0
  33. data/ext/LZInWindow.cpp +102 -0
  34. data/ext/LZInWindow.h +84 -0
  35. data/ext/LZMA.h +82 -0
  36. data/ext/LZMADecoder.h +248 -0
  37. data/ext/LZMAEncoder.cpp +1504 -0
  38. data/ext/LZMAEncoder.h +416 -0
  39. data/ext/LZOutWindow.cpp +17 -0
  40. data/ext/LZOutWindow.h +66 -0
  41. data/ext/LzmaBench.h +11 -0
  42. data/ext/LzmaDecode.c +588 -0
  43. data/ext/LzmaDecode.h +131 -0
  44. data/ext/LzmaRam.cpp +228 -0
  45. data/ext/LzmaRam.h +46 -0
  46. data/ext/LzmaRamDecode.c +79 -0
  47. data/ext/LzmaRamDecode.h +55 -0
  48. data/ext/MyCom.h +203 -0
  49. data/ext/MyGuidDef.h +54 -0
  50. data/ext/MyInitGuid.h +13 -0
  51. data/ext/MyString.h +631 -0
  52. data/ext/MyUnknown.h +24 -0
  53. data/ext/MyWindows.h +183 -0
  54. data/ext/OutBuffer.cpp +117 -0
  55. data/ext/OutBuffer.h +64 -0
  56. data/ext/Pat.h +318 -0
  57. data/ext/Pat2.h +22 -0
  58. data/ext/Pat2H.h +24 -0
  59. data/ext/Pat2R.h +20 -0
  60. data/ext/Pat3H.h +24 -0
  61. data/ext/Pat4H.h +24 -0
  62. data/ext/PatMain.h +989 -0
  63. data/ext/RangeCoder.h +205 -0
  64. data/ext/RangeCoderBit.cpp +80 -0
  65. data/ext/RangeCoderBit.h +120 -0
  66. data/ext/RangeCoderBitTree.h +161 -0
  67. data/ext/RangeCoderOpt.h +31 -0
  68. data/ext/StdAfx.h +8 -0
  69. data/ext/StreamUtils.cpp +44 -0
  70. data/ext/StreamUtils.h +11 -0
  71. data/ext/StringConvert.h +71 -0
  72. data/ext/StringToInt.h +17 -0
  73. data/ext/Types.h +19 -0
  74. data/ext/Vector.h +211 -0
  75. data/ext/extconf.rb +7 -0
  76. data/ext/lzma_ruby.cpp +51 -0
  77. data/ext/lzmalib.h +64 -0
  78. data/ext/mylib.cpp +81 -0
  79. data/java/SevenZip/CRC.java +52 -0
  80. data/java/SevenZip/Compression/LZ/BinTree.java +382 -0
  81. data/java/SevenZip/Compression/LZ/InWindow.java +131 -0
  82. data/java/SevenZip/Compression/LZ/OutWindow.java +85 -0
  83. data/java/SevenZip/Compression/LZMA/Base.java +88 -0
  84. data/java/SevenZip/Compression/LZMA/Decoder.java +329 -0
  85. data/java/SevenZip/Compression/LZMA/Encoder.java +1415 -0
  86. data/java/SevenZip/Compression/RangeCoder/BitTreeDecoder.java +55 -0
  87. data/java/SevenZip/Compression/RangeCoder/BitTreeEncoder.java +99 -0
  88. data/java/SevenZip/Compression/RangeCoder/Decoder.java +88 -0
  89. data/java/SevenZip/Compression/RangeCoder/Encoder.java +151 -0
  90. data/java/SevenZip/ICodeProgress.java +6 -0
  91. data/java/SevenZip/LzmaAlone.java +253 -0
  92. data/java/SevenZip/LzmaBench.java +391 -0
  93. data/java/com/ephemeronindustries/lzma/LZMA.java +104 -0
  94. data/lib/lzma.rb +32 -0
  95. data/ruby-lzma.gemspec +136 -0
  96. data/test/test_lzma.rb +42 -0
  97. metadata +157 -0
data/.gitignore ADDED
@@ -0,0 +1,6 @@
1
+ java/lzma_java.jar
2
+ *.class
3
+ *.o
4
+ *.bundle
5
+ *.gem
6
+ ext/Makefile
data/README.markdown ADDED
@@ -0,0 +1,15 @@
1
+ # LZMA Ruby bindings
2
+
3
+ ## Java and MRI
4
+
5
+ ## Examples
6
+
7
+ ### Compressing String Data:
8
+
9
+ require 'lzma'
10
+ compressed = LZMA.compress('data to compress')
11
+
12
+ ### Decompressing String Data:
13
+
14
+ require 'lzma'
15
+ decompressed = LZMA.decompress(File.read("compressed.lzma"))
data/Rakefile ADDED
@@ -0,0 +1,53 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+
4
+ if RUBY_PLATFORM =~ /java/
5
+ desc "compile .java to .class"
6
+ task :compile do
7
+ chdir('java') do
8
+ sh 'javac com/ephemeronindustries/lzma/*.java'
9
+ sh 'javac SevenZip/Compression/LZ/*.java'
10
+ sh 'javac SevenZip/Compression/LZMA/*.java'
11
+ sh 'javac SevenZip/Compression/RangeCoder/*.java'
12
+ end
13
+ end
14
+
15
+ desc "compile .classes to .jar"
16
+ task :jar => [:compile] do
17
+ chdir('java') do
18
+ sh "jar -cf lzma_java.jar com/ephemeronindustries/lzma/*.class SevenZip/Compression/LZ/*.class SevenZip/Compression/LZMA/*.class SevenZip/Compression/RangeCoder/*.class"
19
+ end
20
+ end
21
+
22
+ else
23
+ desc "compile C extension"
24
+ task :compile do
25
+ chdir('ext') do
26
+ sh 'ruby extconf.rb'
27
+ sh 'make'
28
+ end
29
+ end
30
+ end
31
+
32
+ task :default => :test
33
+
34
+ Rake::TestTask.new(:test) do |t|
35
+ t.test_files = FileList['test/test_*.rb']
36
+ t.verbose = false
37
+ end
38
+
39
+ task :test => :compile
40
+
41
+ begin
42
+ require 'jeweler'
43
+ Jeweler::Tasks.new do |gemspec|
44
+ gemspec.name = "ruby-lzma"
45
+ gemspec.summary = "Simple ruby and jruby wrappers for LZMA compression and decompression."
46
+ gemspec.description = "A different and possibly longer explanation of"
47
+ gemspec.email = "ian@ianlevesque.org"
48
+ gemspec.homepage = "http://github.com/ianlevesque/ruby-lzma"
49
+ gemspec.authors = ["Ian Levesque"]
50
+ end
51
+ rescue LoadError
52
+ puts "Jeweler not available. Install it with: gem install jeweler"
53
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.4.1
data/ext/Alloc.cpp ADDED
@@ -0,0 +1,118 @@
1
+ // Common/Alloc.cpp
2
+
3
+ #include "StdAfx.h"
4
+
5
+ #ifdef _WIN32
6
+ #include "MyWindows.h"
7
+ #else
8
+ #include <stdlib.h>
9
+ #endif
10
+
11
+ #include "Alloc.h"
12
+
13
+ /* #define _SZ_ALLOC_DEBUG */
14
+ /* use _SZ_ALLOC_DEBUG to debug alloc/free operations */
15
+ #ifdef _SZ_ALLOC_DEBUG
16
+ #include <stdio.h>
17
+ int g_allocCount = 0;
18
+ int g_allocCountMid = 0;
19
+ int g_allocCountBig = 0;
20
+ #endif
21
+
22
+ void *MyAlloc(size_t size) throw()
23
+ {
24
+ if (size == 0)
25
+ return 0;
26
+ #ifdef _SZ_ALLOC_DEBUG
27
+ fprintf(stderr, "\nAlloc %10d bytes; count = %10d", size, g_allocCount++);
28
+ #endif
29
+ return ::malloc(size);
30
+ }
31
+
32
+ void MyFree(void *address) throw()
33
+ {
34
+ #ifdef _SZ_ALLOC_DEBUG
35
+ if (address != 0)
36
+ fprintf(stderr, "\nFree; count = %10d", --g_allocCount);
37
+ #endif
38
+
39
+ ::free(address);
40
+ }
41
+
42
+ #ifdef _WIN32
43
+
44
+ void *MidAlloc(size_t size) throw()
45
+ {
46
+ if (size == 0)
47
+ return 0;
48
+ #ifdef _SZ_ALLOC_DEBUG
49
+ fprintf(stderr, "\nAlloc_Mid %10d bytes; count = %10d", size, g_allocCountMid++);
50
+ #endif
51
+ return ::VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE);
52
+ }
53
+
54
+ void MidFree(void *address) throw()
55
+ {
56
+ #ifdef _SZ_ALLOC_DEBUG
57
+ if (address != 0)
58
+ fprintf(stderr, "\nFree_Mid; count = %10d", --g_allocCountMid);
59
+ #endif
60
+ if (address == 0)
61
+ return;
62
+ ::VirtualFree(address, 0, MEM_RELEASE);
63
+ }
64
+
65
+ static SIZE_T g_LargePageSize =
66
+ #ifdef _WIN64
67
+ (1 << 21);
68
+ #else
69
+ (1 << 22);
70
+ #endif
71
+
72
+ typedef SIZE_T (WINAPI *GetLargePageMinimumP)();
73
+
74
+ bool SetLargePageSize()
75
+ {
76
+ GetLargePageMinimumP largePageMinimum = (GetLargePageMinimumP)
77
+ ::GetProcAddress(::GetModuleHandle(TEXT("kernel32.dll")), "GetLargePageMinimum");
78
+ if (largePageMinimum == 0)
79
+ return false;
80
+ SIZE_T size = largePageMinimum();
81
+ if (size == 0 || (size & (size - 1)) != 0)
82
+ return false;
83
+ g_LargePageSize = size;
84
+ return true;
85
+ }
86
+
87
+
88
+ void *BigAlloc(size_t size) throw()
89
+ {
90
+ if (size == 0)
91
+ return 0;
92
+ #ifdef _SZ_ALLOC_DEBUG
93
+ fprintf(stderr, "\nAlloc_Big %10d bytes; count = %10d", size, g_allocCountBig++);
94
+ #endif
95
+
96
+ if (size >= (1 << 18))
97
+ {
98
+ void *res = ::VirtualAlloc(0, (size + g_LargePageSize - 1) & (~(g_LargePageSize - 1)),
99
+ MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE);
100
+ if (res != 0)
101
+ return res;
102
+ }
103
+ return ::VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE);
104
+ }
105
+
106
+ void BigFree(void *address) throw()
107
+ {
108
+ #ifdef _SZ_ALLOC_DEBUG
109
+ if (address != 0)
110
+ fprintf(stderr, "\nFree_Big; count = %10d", --g_allocCountBig);
111
+ #endif
112
+
113
+ if (address == 0)
114
+ return;
115
+ ::VirtualFree(address, 0, MEM_RELEASE);
116
+ }
117
+
118
+ #endif
data/ext/Alloc.h ADDED
@@ -0,0 +1,29 @@
1
+ // Common/Alloc.h
2
+
3
+ #ifndef __COMMON_ALLOC_H
4
+ #define __COMMON_ALLOC_H
5
+
6
+ #include <stddef.h>
7
+
8
+ void *MyAlloc(size_t size) throw();
9
+ void MyFree(void *address) throw();
10
+
11
+ #ifdef _WIN32
12
+
13
+ bool SetLargePageSize();
14
+
15
+ void *MidAlloc(size_t size) throw();
16
+ void MidFree(void *address) throw();
17
+ void *BigAlloc(size_t size) throw();
18
+ void BigFree(void *address) throw();
19
+
20
+ #else
21
+
22
+ #define MidAlloc(size) MyAlloc(size)
23
+ #define MidFree(address) MyFree(address)
24
+ #define BigAlloc(size) MyAlloc(size)
25
+ #define BigFree(address) MyFree(address)
26
+
27
+ #endif
28
+
29
+ #endif
data/ext/BinTree.h ADDED
@@ -0,0 +1,55 @@
1
+ // BinTree.h
2
+
3
+ #include "LZInWindow.h"
4
+ #include "IMatchFinder.h"
5
+
6
+ namespace BT_NAMESPACE {
7
+
8
+ typedef UInt32 CIndex;
9
+ const UInt32 kMaxValForNormalize = (UInt32(1) << 31) - 1;
10
+
11
+ class CMatchFinderBinTree:
12
+ public IMatchFinder,
13
+ public IMatchFinderSetCallback,
14
+ public CLZInWindow,
15
+ public CMyUnknownImp
16
+ {
17
+ UInt32 _cyclicBufferPos;
18
+ UInt32 _cyclicBufferSize; // it must be historySize + 1
19
+ UInt32 _matchMaxLen;
20
+ CIndex *_hash;
21
+ UInt32 _cutValue;
22
+
23
+ CMyComPtr<IMatchFinderCallback> m_Callback;
24
+
25
+ void Normalize();
26
+ void FreeThisClassMemory();
27
+ void FreeMemory();
28
+
29
+ MY_UNKNOWN_IMP1(IMatchFinderSetCallback)
30
+
31
+ STDMETHOD(Init)(ISequentialInStream *inStream);
32
+ STDMETHOD_(void, ReleaseStream)();
33
+ STDMETHOD(MovePos)();
34
+ STDMETHOD_(Byte, GetIndexByte)(Int32 index);
35
+ STDMETHOD_(UInt32, GetMatchLen)(Int32 index, UInt32 back, UInt32 limit);
36
+ STDMETHOD_(UInt32, GetNumAvailableBytes)();
37
+ STDMETHOD_(const Byte *, GetPointerToCurrentPos)();
38
+ STDMETHOD(Create)(UInt32 historySize, UInt32 keepAddBufferBefore,
39
+ UInt32 matchMaxLen, UInt32 keepAddBufferAfter);
40
+ STDMETHOD_(UInt32, GetLongestMatch)(UInt32 *distances);
41
+ STDMETHOD_(void, DummyLongestMatch)();
42
+
43
+ // IMatchFinderSetCallback
44
+ STDMETHOD(SetCallback)(IMatchFinderCallback *callback);
45
+
46
+ virtual void BeforeMoveBlock();
47
+ virtual void AfterMoveBlock();
48
+
49
+ public:
50
+ CMatchFinderBinTree();
51
+ virtual ~CMatchFinderBinTree();
52
+ void SetCutValue(UInt32 cutValue) { _cutValue = cutValue; }
53
+ };
54
+
55
+ }
data/ext/BinTree2.h ADDED
@@ -0,0 +1,12 @@
1
+ // BinTree2.h
2
+
3
+ #ifndef __BINTREE2_H
4
+ #define __BINTREE2_H
5
+
6
+ #undef BT_NAMESPACE
7
+ #define BT_NAMESPACE NBT2
8
+
9
+ #include "BinTree.h"
10
+ #include "BinTreeMain.h"
11
+
12
+ #endif
data/ext/BinTree3.h ADDED
@@ -0,0 +1,16 @@
1
+ // BinTree3.h
2
+
3
+ #ifndef __BINTREE3_H
4
+ #define __BINTREE3_H
5
+
6
+ #undef BT_NAMESPACE
7
+ #define BT_NAMESPACE NBT3
8
+
9
+ #define HASH_ARRAY_2
10
+
11
+ #include "BinTree.h"
12
+ #include "BinTreeMain.h"
13
+
14
+ #undef HASH_ARRAY_2
15
+
16
+ #endif
data/ext/BinTree3Z.h ADDED
@@ -0,0 +1,16 @@
1
+ // BinTree3Z.h
2
+
3
+ #ifndef __BINTREE3Z_H
4
+ #define __BINTREE3Z_H
5
+
6
+ #undef BT_NAMESPACE
7
+ #define BT_NAMESPACE NBT3Z
8
+
9
+ #define HASH_ZIP
10
+
11
+ #include "BinTree.h"
12
+ #include "BinTreeMain.h"
13
+
14
+ #undef HASH_ZIP
15
+
16
+ #endif
data/ext/BinTree4.h ADDED
@@ -0,0 +1,18 @@
1
+ // BinTree4.h
2
+
3
+ #ifndef __BINTREE4_H
4
+ #define __BINTREE4_H
5
+
6
+ #undef BT_NAMESPACE
7
+ #define BT_NAMESPACE NBT4
8
+
9
+ #define HASH_ARRAY_2
10
+ #define HASH_ARRAY_3
11
+
12
+ #include "BinTree.h"
13
+ #include "BinTreeMain.h"
14
+
15
+ #undef HASH_ARRAY_2
16
+ #undef HASH_ARRAY_3
17
+
18
+ #endif
data/ext/BinTree4b.h ADDED
@@ -0,0 +1,20 @@
1
+ // BinTree4b.h
2
+
3
+ #ifndef __BINTREE4B_H
4
+ #define __BINTREE4B_H
5
+
6
+ #undef BT_NAMESPACE
7
+ #define BT_NAMESPACE NBT4B
8
+
9
+ #define HASH_ARRAY_2
10
+ #define HASH_ARRAY_3
11
+ #define HASH_BIG
12
+
13
+ #include "BinTree.h"
14
+ #include "BinTreeMain.h"
15
+
16
+ #undef HASH_ARRAY_2
17
+ #undef HASH_ARRAY_3
18
+ #undef HASH_BIG
19
+
20
+ #endif
data/ext/BinTreeMain.h ADDED
@@ -0,0 +1,444 @@
1
+ // BinTreeMain.h
2
+
3
+ #include "Defs.h"
4
+ #include "CRC.h"
5
+ #include "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
+ }