ruby-lzma 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
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
+ }