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.
- data/.gitignore +6 -0
- data/README.markdown +15 -0
- data/Rakefile +53 -0
- data/VERSION +1 -0
- data/ext/Alloc.cpp +118 -0
- data/ext/Alloc.h +29 -0
- data/ext/BinTree.h +55 -0
- data/ext/BinTree2.h +12 -0
- data/ext/BinTree3.h +16 -0
- data/ext/BinTree3Z.h +16 -0
- data/ext/BinTree4.h +18 -0
- data/ext/BinTree4b.h +20 -0
- data/ext/BinTreeMain.h +444 -0
- data/ext/BranchX86.c +101 -0
- data/ext/BranchX86.h +19 -0
- data/ext/CRC.cpp +61 -0
- data/ext/CRC.h +36 -0
- data/ext/C_FileIO.h +45 -0
- data/ext/CommandLineParser.h +82 -0
- data/ext/Defs.h +20 -0
- data/ext/FileStreams.h +98 -0
- data/ext/HC.h +55 -0
- data/ext/HC2.h +13 -0
- data/ext/HC3.h +17 -0
- data/ext/HC4.h +19 -0
- data/ext/HC4b.h +21 -0
- data/ext/HCMain.h +350 -0
- data/ext/ICoder.h +156 -0
- data/ext/IMatchFinder.h +63 -0
- data/ext/IStream.h +62 -0
- data/ext/InBuffer.cpp +80 -0
- data/ext/InBuffer.h +76 -0
- data/ext/LZInWindow.cpp +102 -0
- data/ext/LZInWindow.h +84 -0
- data/ext/LZMA.h +82 -0
- data/ext/LZMADecoder.h +248 -0
- data/ext/LZMAEncoder.cpp +1504 -0
- data/ext/LZMAEncoder.h +416 -0
- data/ext/LZOutWindow.cpp +17 -0
- data/ext/LZOutWindow.h +66 -0
- data/ext/LzmaBench.h +11 -0
- data/ext/LzmaDecode.c +588 -0
- data/ext/LzmaDecode.h +131 -0
- data/ext/LzmaRam.cpp +228 -0
- data/ext/LzmaRam.h +46 -0
- data/ext/LzmaRamDecode.c +79 -0
- data/ext/LzmaRamDecode.h +55 -0
- data/ext/MyCom.h +203 -0
- data/ext/MyGuidDef.h +54 -0
- data/ext/MyInitGuid.h +13 -0
- data/ext/MyString.h +631 -0
- data/ext/MyUnknown.h +24 -0
- data/ext/MyWindows.h +183 -0
- data/ext/OutBuffer.cpp +117 -0
- data/ext/OutBuffer.h +64 -0
- data/ext/Pat.h +318 -0
- data/ext/Pat2.h +22 -0
- data/ext/Pat2H.h +24 -0
- data/ext/Pat2R.h +20 -0
- data/ext/Pat3H.h +24 -0
- data/ext/Pat4H.h +24 -0
- data/ext/PatMain.h +989 -0
- data/ext/RangeCoder.h +205 -0
- data/ext/RangeCoderBit.cpp +80 -0
- data/ext/RangeCoderBit.h +120 -0
- data/ext/RangeCoderBitTree.h +161 -0
- data/ext/RangeCoderOpt.h +31 -0
- data/ext/StdAfx.h +8 -0
- data/ext/StreamUtils.cpp +44 -0
- data/ext/StreamUtils.h +11 -0
- data/ext/StringConvert.h +71 -0
- data/ext/StringToInt.h +17 -0
- data/ext/Types.h +19 -0
- data/ext/Vector.h +211 -0
- data/ext/extconf.rb +7 -0
- data/ext/lzma_ruby.cpp +51 -0
- data/ext/lzmalib.h +64 -0
- data/ext/mylib.cpp +81 -0
- data/java/SevenZip/CRC.java +52 -0
- data/java/SevenZip/Compression/LZ/BinTree.java +382 -0
- data/java/SevenZip/Compression/LZ/InWindow.java +131 -0
- data/java/SevenZip/Compression/LZ/OutWindow.java +85 -0
- data/java/SevenZip/Compression/LZMA/Base.java +88 -0
- data/java/SevenZip/Compression/LZMA/Decoder.java +329 -0
- data/java/SevenZip/Compression/LZMA/Encoder.java +1415 -0
- data/java/SevenZip/Compression/RangeCoder/BitTreeDecoder.java +55 -0
- data/java/SevenZip/Compression/RangeCoder/BitTreeEncoder.java +99 -0
- data/java/SevenZip/Compression/RangeCoder/Decoder.java +88 -0
- data/java/SevenZip/Compression/RangeCoder/Encoder.java +151 -0
- data/java/SevenZip/ICodeProgress.java +6 -0
- data/java/SevenZip/LzmaAlone.java +253 -0
- data/java/SevenZip/LzmaBench.java +391 -0
- data/java/com/ephemeronindustries/lzma/LZMA.java +104 -0
- data/lib/lzma.rb +32 -0
- data/ruby-lzma.gemspec +136 -0
- data/test/test_lzma.rb +42 -0
- metadata +157 -0
data/.gitignore
ADDED
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
data/ext/BinTree3.h
ADDED
data/ext/BinTree3Z.h
ADDED
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
|
+
}
|