rbzip2 0.1.0
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 +3 -0
- data/.travis.yml +9 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +28 -0
- data/LICENSE +25 -0
- data/README.md +59 -0
- data/Rakefile +39 -0
- data/lib/rbzip2/constants.rb +66 -0
- data/lib/rbzip2/crc.rb +105 -0
- data/lib/rbzip2/data.rb +51 -0
- data/lib/rbzip2/decompressor.rb +684 -0
- data/lib/rbzip2/io.rb +25 -0
- data/lib/rbzip2/version.rb +10 -0
- data/lib/rbzip2.rb +14 -0
- data/rbzip2.gemspec +27 -0
- data/spec/fixtures/test.bz2 +0 -0
- data/spec/fixtures/test.txt +11 -0
- data/spec/helper.rb +12 -0
- data/spec/io_spec.rb +37 -0
- metadata +166 -0
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
rbzip2 (0.1.0)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: http://rubygems.org/
|
8
|
+
specs:
|
9
|
+
diff-lcs (1.1.3)
|
10
|
+
metaclass (0.0.1)
|
11
|
+
mocha (0.10.0)
|
12
|
+
metaclass (~> 0.0.1)
|
13
|
+
rake (0.9.2.2)
|
14
|
+
rspec-core (2.7.1)
|
15
|
+
rspec-expectations (2.7.0)
|
16
|
+
diff-lcs (~> 1.1.2)
|
17
|
+
yard (0.7.3)
|
18
|
+
|
19
|
+
PLATFORMS
|
20
|
+
ruby
|
21
|
+
|
22
|
+
DEPENDENCIES
|
23
|
+
mocha (~> 0.10.0)
|
24
|
+
rake (~> 0.9.2)
|
25
|
+
rbzip2!
|
26
|
+
rspec-core (~> 2.7.1)
|
27
|
+
rspec-expectations (~> 2.7.0)
|
28
|
+
yard (~> 0.7.3)
|
data/LICENSE
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
Copyright (c) 2011, Sebastian Staudt
|
2
|
+
All rights reserved.
|
3
|
+
|
4
|
+
Redistribution and use in source and binary forms, with or without modification,
|
5
|
+
are permitted provided that the following conditions are met:
|
6
|
+
|
7
|
+
* Redistributions of source code must retain the above copyright notice,
|
8
|
+
this list of conditions and the following disclaimer.
|
9
|
+
* Redistributions in binary form must reproduce the above copyright notice,
|
10
|
+
this list of conditions and the following disclaimer in the documentation
|
11
|
+
and/or other materials provided with the distribution.
|
12
|
+
* Neither the name of the author nor the names of its contributors
|
13
|
+
may be used to endorse or promote products derived from this software
|
14
|
+
without specific prior written permission.
|
15
|
+
|
16
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
17
|
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
18
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
19
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
20
|
+
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
21
|
+
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
22
|
+
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
23
|
+
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
24
|
+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
25
|
+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/README.md
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
RBzip2
|
2
|
+
======
|
3
|
+
|
4
|
+
RBzip2 is a gem providing a pure Ruby implementation of the [bzip2][1]
|
5
|
+
algorithm used for compression and decompression.
|
6
|
+
|
7
|
+
It is based on the code of the [Apache Commons Compress][2] project and adds
|
8
|
+
a straight Ruby-like API. There are no external dependencies like other gems or
|
9
|
+
libraries. Therefore it will run on any Ruby implementation and the respective
|
10
|
+
operating systems supported by those implementations.
|
11
|
+
|
12
|
+
## Features
|
13
|
+
|
14
|
+
* Decompression of bzip2 compressed IOs (like `File` or `StringIO`)
|
15
|
+
|
16
|
+
## Usage
|
17
|
+
|
18
|
+
require 'rbzip2'
|
19
|
+
|
20
|
+
file = File.new 'somefile.bz2' # open a compressed file
|
21
|
+
io = RBzip2::IO.new file # wrap the file into RBzip2's IO
|
22
|
+
data = io.read # read data into a string
|
23
|
+
|
24
|
+
## Future plans
|
25
|
+
|
26
|
+
* Simple decompression of strings
|
27
|
+
* Compression of raw data
|
28
|
+
* Simple creation of compressed files
|
29
|
+
* Two-way compressed IO that will (de)compress as you read/write
|
30
|
+
|
31
|
+
## Installation
|
32
|
+
|
33
|
+
To install RBzip2 as a Ruby gem use the following command:
|
34
|
+
|
35
|
+
gem install rbzip2
|
36
|
+
|
37
|
+
To use it as a dependency managed by Bundler add the following to your
|
38
|
+
`Gemfile`:
|
39
|
+
|
40
|
+
gem 'rbzip2'
|
41
|
+
|
42
|
+
## License
|
43
|
+
|
44
|
+
This code is free software; you can redistribute it and/or modify it under the
|
45
|
+
terms of the new BSD License. A copy of this license can be found in the
|
46
|
+
included LICENSE file.
|
47
|
+
|
48
|
+
## Credits
|
49
|
+
|
50
|
+
* Sebastian Staudt -- koraktor(at)gmail.com
|
51
|
+
|
52
|
+
## See Also
|
53
|
+
|
54
|
+
* [Documentation](http://rubydoc.info/gems/rbzip2)
|
55
|
+
* [GitHub project page](https://github.com/koraktor/rbzip2)
|
56
|
+
* [bzip2 project page][1]
|
57
|
+
|
58
|
+
[1]: http://bzip.org
|
59
|
+
[2]: http://commons.apache.org/compress
|
data/Rakefile
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
# This code is free software; you can redistribute it and/or modify it under
|
4
|
+
# the terms of the new BSD License.
|
5
|
+
#
|
6
|
+
# Copyright (c) 2011, Sebastian Staudt
|
7
|
+
|
8
|
+
require 'rspec/core/rake_task'
|
9
|
+
require 'rubygems/package_task'
|
10
|
+
|
11
|
+
task :default => :spec
|
12
|
+
|
13
|
+
spec = Gem::Specification.load 'rbzip2.gemspec'
|
14
|
+
Gem::PackageTask.new(spec) do |pkg|
|
15
|
+
end
|
16
|
+
|
17
|
+
RSpec::Core::RakeTask.new('spec') do |t|
|
18
|
+
end
|
19
|
+
|
20
|
+
begin
|
21
|
+
require 'yard'
|
22
|
+
|
23
|
+
YARD::Rake::YardocTask.new do |yardoc|
|
24
|
+
yardoc.name = 'doc'
|
25
|
+
yardoc.files = [ 'lib/**/*.rb', 'LICENSE', 'README.md' ]
|
26
|
+
yardoc.options = [ '--private', '--title', 'RBzip2 — API Documentation' ]
|
27
|
+
end
|
28
|
+
rescue LoadError
|
29
|
+
desc 'Generate YARD Documentation (not available)'
|
30
|
+
task :doc do
|
31
|
+
$stderr.puts 'You need YARD to build the documentation. Install it using `gem install yard`.'
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
desc 'Clean documentation and package directories'
|
36
|
+
task :clean do
|
37
|
+
FileUtils.rm_rf 'doc'
|
38
|
+
FileUtils.rm_rf 'pkg'
|
39
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# This code is free software; you can redistribute it and/or modify it under
|
2
|
+
# the terms of the new BSD License.
|
3
|
+
#
|
4
|
+
# Copyright (c) 2011, Sebastian Staudt
|
5
|
+
|
6
|
+
module RBzip2
|
7
|
+
|
8
|
+
BASEBLOCKSIZE = 100000
|
9
|
+
MAX_ALPHA_SIZE = 258
|
10
|
+
MAX_CODE_LEN = 23
|
11
|
+
RUNA = 0
|
12
|
+
RUNB = 1
|
13
|
+
N_GROUPS = 6
|
14
|
+
G_SIZE = 50
|
15
|
+
N_ITERS = 4
|
16
|
+
MAX_SELECTORS = (2 + (900000 / G_SIZE))
|
17
|
+
NUM_OVERSHOOT_BYTES = 20
|
18
|
+
|
19
|
+
EOF = 0
|
20
|
+
START_BLOCK_STATE = 1
|
21
|
+
RAND_PART_A_STATE = 2
|
22
|
+
RAND_PART_B_STATE = 3
|
23
|
+
RAND_PART_C_STATE = 4
|
24
|
+
NO_RAND_PART_A_STATE = 5
|
25
|
+
NO_RAND_PART_B_STATE = 6
|
26
|
+
NO_RAND_PART_C_STATE = 7
|
27
|
+
|
28
|
+
RNUMS = [
|
29
|
+
619, 720, 127, 481, 931, 816, 813, 233, 566, 247, 985, 724, 205, 454, 863,
|
30
|
+
491, 741, 242, 949, 214, 733, 859, 335, 708, 621, 574, 73, 654, 730, 472,
|
31
|
+
419, 436, 278, 496, 867, 210, 399, 680, 480, 51, 878, 465, 811, 169, 869,
|
32
|
+
675, 611, 697, 867, 561, 862, 687, 507, 283, 482, 129, 807, 591, 733, 623,
|
33
|
+
150, 238, 59, 379, 684, 877, 625, 169, 643, 105, 170, 607, 520, 932, 727,
|
34
|
+
476, 693, 425, 174, 647, 73, 122, 335, 530, 442, 853, 695, 249, 445, 515,
|
35
|
+
909, 545, 703, 919, 874, 474, 882, 500, 594, 612, 641, 801, 220, 162, 819,
|
36
|
+
984, 589, 513, 495, 799, 161, 604, 958, 533, 221, 400, 386, 867, 600, 782,
|
37
|
+
382, 596, 414, 171, 516, 375, 682, 485, 911, 276, 98, 553, 163, 354, 666,
|
38
|
+
933, 424, 341, 533, 870, 227, 730, 475, 186, 263, 647, 537, 686, 600, 224,
|
39
|
+
469, 68, 770, 919, 190, 373, 294, 822, 808, 206, 184, 943, 795, 384, 383,
|
40
|
+
461, 404, 758, 839, 887, 715, 67, 618, 276, 204, 918, 873, 777, 604, 560,
|
41
|
+
951, 160, 578, 722, 79, 804, 96, 409, 713, 940, 652, 934, 970, 447, 318,
|
42
|
+
353, 859, 672, 112, 785, 645, 863, 803, 350, 139, 93, 354, 99, 820, 908,
|
43
|
+
609, 772, 154, 274, 580, 184, 79, 626, 630, 742, 653, 282, 762, 623, 680,
|
44
|
+
81, 927, 626, 789, 125, 411, 521, 938, 300, 821, 78, 343, 175, 128, 250,
|
45
|
+
170, 774, 972, 275, 999, 639, 495, 78, 352, 126, 857, 956, 358, 619, 580,
|
46
|
+
124, 737, 594, 701, 612, 669, 112, 134, 694, 363, 992, 809, 743, 168, 974,
|
47
|
+
944, 375, 748, 52, 600, 747, 642, 182, 862, 81, 344, 805, 988, 739, 511,
|
48
|
+
655, 814, 334, 249, 515, 897, 955, 664, 981, 649, 113, 974, 459, 893, 228,
|
49
|
+
433, 837, 553, 268, 926, 240, 102, 654, 459, 51, 686, 754, 806, 760, 493,
|
50
|
+
403, 415, 394, 687, 700, 946, 670, 656, 610, 738, 392, 760, 799, 887, 653,
|
51
|
+
978, 321, 576, 617, 626, 502, 894, 679, 243, 440, 680, 879, 194, 572, 640,
|
52
|
+
724, 926, 56, 204, 700, 707, 151, 457, 449, 797, 195, 791, 558, 945, 679,
|
53
|
+
297, 59, 87, 824, 713, 663, 412, 693, 342, 606, 134, 108, 571, 364, 631,
|
54
|
+
212, 174, 643, 304, 329, 343, 97, 430, 751, 497, 314, 983, 374, 822, 928,
|
55
|
+
140, 206, 73, 263, 980, 736, 876, 478, 430, 305, 170, 514, 364, 692, 829,
|
56
|
+
82, 855, 953, 676, 246, 369, 970, 294, 750, 807, 827, 150, 790, 288, 923,
|
57
|
+
804, 378, 215, 828, 592, 281, 565, 555, 710, 82, 896, 831, 547, 261, 524,
|
58
|
+
462, 293, 465, 502, 56, 661, 821, 976, 991, 658, 869, 905, 758, 745, 193,
|
59
|
+
768, 550, 608, 933, 378, 286, 215, 979, 792, 961, 61, 688, 793, 644, 986,
|
60
|
+
403, 106, 366, 905, 644, 372, 567, 466, 434, 645, 210, 389, 550, 919, 135,
|
61
|
+
780, 773, 635, 389, 707, 100, 626, 958, 165, 504, 920, 176, 193, 713, 857,
|
62
|
+
265, 203, 50, 668, 108, 645, 990, 626, 197, 510, 357, 358, 850, 858, 364,
|
63
|
+
936, 638
|
64
|
+
]
|
65
|
+
|
66
|
+
end
|
data/lib/rbzip2/crc.rb
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
# This code is free software; you can redistribute it and/or modify it under
|
2
|
+
# the terms of the new BSD License.
|
3
|
+
#
|
4
|
+
# Copyright (c) 2011, Sebastian Staudt
|
5
|
+
|
6
|
+
class RBzip2::CRC
|
7
|
+
|
8
|
+
CRC32_TABLE = [
|
9
|
+
0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9,
|
10
|
+
0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
|
11
|
+
0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
|
12
|
+
0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
|
13
|
+
0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9,
|
14
|
+
0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
|
15
|
+
0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011,
|
16
|
+
0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd,
|
17
|
+
0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
|
18
|
+
0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5,
|
19
|
+
0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81,
|
20
|
+
0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
|
21
|
+
0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49,
|
22
|
+
0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
|
23
|
+
0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
|
24
|
+
0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d,
|
25
|
+
0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae,
|
26
|
+
0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
|
27
|
+
0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
|
28
|
+
0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca,
|
29
|
+
0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
|
30
|
+
0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02,
|
31
|
+
0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066,
|
32
|
+
0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
|
33
|
+
0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e,
|
34
|
+
0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692,
|
35
|
+
0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
|
36
|
+
0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a,
|
37
|
+
0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
|
38
|
+
0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
|
39
|
+
0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686,
|
40
|
+
0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a,
|
41
|
+
0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
|
42
|
+
0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
|
43
|
+
0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f,
|
44
|
+
0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
|
45
|
+
0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47,
|
46
|
+
0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b,
|
47
|
+
0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
|
48
|
+
0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623,
|
49
|
+
0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7,
|
50
|
+
0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
|
51
|
+
0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f,
|
52
|
+
0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
|
53
|
+
0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
|
54
|
+
0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b,
|
55
|
+
0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f,
|
56
|
+
0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
|
57
|
+
0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
|
58
|
+
0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c,
|
59
|
+
0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
|
60
|
+
0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24,
|
61
|
+
0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30,
|
62
|
+
0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
|
63
|
+
0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088,
|
64
|
+
0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654,
|
65
|
+
0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
|
66
|
+
0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c,
|
67
|
+
0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
|
68
|
+
0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
|
69
|
+
0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0,
|
70
|
+
0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c,
|
71
|
+
0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
|
72
|
+
0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
|
73
|
+
]
|
74
|
+
|
75
|
+
attr_accessor :global_crc
|
76
|
+
|
77
|
+
def initialize
|
78
|
+
initialize_crc
|
79
|
+
end
|
80
|
+
|
81
|
+
def initialize_crc
|
82
|
+
@global_crc = 0xffffffff
|
83
|
+
end
|
84
|
+
|
85
|
+
def final_crc
|
86
|
+
@global_crc ^ 0xffffffff
|
87
|
+
end
|
88
|
+
|
89
|
+
def update_crc(in_ch, repeat = -1)
|
90
|
+
if repeat == -1
|
91
|
+
temp = ((@global_crc >> 24) ^ in_ch) % 256
|
92
|
+
temp = 256 + temp if temp < 0
|
93
|
+
@global_crc = ((@global_crc << 8) ^ CRC32_TABLE[temp]) % 2**32
|
94
|
+
else
|
95
|
+
global_crc_shadow = @global_crc
|
96
|
+
repeat.downto(0) do
|
97
|
+
temp = ((global_crc_shadow >> 24) ^ in_ch) % 256
|
98
|
+
temp = 256 + temp if temp < 0
|
99
|
+
global_crc_shadow = (global_crc_shadow << 8) ^ CRC32_TABLE[temp]
|
100
|
+
end
|
101
|
+
@global_crc = global_crc_shadow % 2**32
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
data/lib/rbzip2/data.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
# This code is free software; you can redistribute it and/or modify it under
|
2
|
+
# the terms of the new BSD License.
|
3
|
+
#
|
4
|
+
# Copyright (c) 2011, Sebastian Staudt
|
5
|
+
|
6
|
+
require 'rbzip2/constants'
|
7
|
+
|
8
|
+
class RBzip2::Data
|
9
|
+
|
10
|
+
attr_reader :base, :cftab, :get_and_move_to_front_decode_yy, :in_use,
|
11
|
+
:limit, :ll8, :min_lens, :perm, :receive_decoding_tables_pos,
|
12
|
+
:selector, :selector_mtf, :seq_to_unseq, :temp_char_array_2d,
|
13
|
+
:unzftab, :tt
|
14
|
+
|
15
|
+
def initialize(block_size)
|
16
|
+
@in_use = Array.new 256, false
|
17
|
+
|
18
|
+
@seq_to_unseq = Array.new 256, 0
|
19
|
+
@selector = Array.new RBzip2::MAX_SELECTORS, 0
|
20
|
+
@selector_mtf = Array.new RBzip2::MAX_SELECTORS, 0
|
21
|
+
|
22
|
+
@unzftab = Array.new 256, 0
|
23
|
+
|
24
|
+
@base = Array.new RBzip2::N_GROUPS
|
25
|
+
RBzip2::N_GROUPS.times { |i| @base[i] = Array.new(RBzip2::MAX_ALPHA_SIZE, 0) }
|
26
|
+
@limit = Array.new RBzip2::N_GROUPS
|
27
|
+
RBzip2::N_GROUPS.times { |i| @limit[i] = Array.new(RBzip2::MAX_ALPHA_SIZE, 0) }
|
28
|
+
@perm = Array.new RBzip2::N_GROUPS
|
29
|
+
RBzip2:: N_GROUPS.times { |i| @perm[i] = Array.new(RBzip2::MAX_ALPHA_SIZE, 0) }
|
30
|
+
@min_lens = Array.new RBzip2::N_GROUPS, 0
|
31
|
+
|
32
|
+
@cftab = Array.new 257, 0
|
33
|
+
@get_and_move_to_front_decode_yy = Array.new 256
|
34
|
+
@temp_char_array_2d = Array.new RBzip2::N_GROUPS
|
35
|
+
RBzip2::N_GROUPS.times { |i| @temp_char_array_2d[i] = Array.new(RBzip2::MAX_ALPHA_SIZE, 0) }
|
36
|
+
@receive_decoding_tables_pos = Array.new RBzip2::N_GROUPS, 0
|
37
|
+
|
38
|
+
@ll8 = Array.new block_size * RBzip2::BASEBLOCKSIZE
|
39
|
+
end
|
40
|
+
|
41
|
+
def init_tt(size)
|
42
|
+
tt_shadow = @tt
|
43
|
+
|
44
|
+
if tt_shadow.nil? || tt_shadow.size < size
|
45
|
+
@tt = tt_shadow = Array.new(size)
|
46
|
+
end
|
47
|
+
|
48
|
+
tt_shadow
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
@@ -0,0 +1,684 @@
|
|
1
|
+
# This code is free software; you can redistribute it and/or modify it under
|
2
|
+
# the terms of the new BSD License.
|
3
|
+
#
|
4
|
+
# Copyright (c) 2011, Sebastian Staudt
|
5
|
+
|
6
|
+
require 'stringio'
|
7
|
+
|
8
|
+
require 'rbzip2/crc'
|
9
|
+
require 'rbzip2/constants'
|
10
|
+
require 'rbzip2/data'
|
11
|
+
|
12
|
+
module RBzip2::Decompressor
|
13
|
+
|
14
|
+
def count(read)
|
15
|
+
@bytes_read += read if read != -1
|
16
|
+
end
|
17
|
+
|
18
|
+
def read(length = uncompressed)
|
19
|
+
raise 'stream closed' if @io.nil?
|
20
|
+
|
21
|
+
if length == 1
|
22
|
+
r = read0
|
23
|
+
count (r < 0 ? -1 : 1)
|
24
|
+
r
|
25
|
+
elsif length > 0
|
26
|
+
r = StringIO.new
|
27
|
+
length.times do
|
28
|
+
b = read0
|
29
|
+
break if b < 0
|
30
|
+
r.write b.chr
|
31
|
+
end
|
32
|
+
count r.size
|
33
|
+
r.string
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def read0
|
38
|
+
ret_char = @current_char
|
39
|
+
|
40
|
+
case @current_state
|
41
|
+
when RBzip2::EOF
|
42
|
+
return -1
|
43
|
+
|
44
|
+
when RBzip2::RAND_PART_B_STATE
|
45
|
+
setup_rand_part_b
|
46
|
+
|
47
|
+
when RBzip2::RAND_PART_C_STATE
|
48
|
+
setup_rand_part_c
|
49
|
+
|
50
|
+
when RBzip2::NO_RAND_PART_B_STATE
|
51
|
+
setup_no_rand_part_b
|
52
|
+
|
53
|
+
when RBzip2::NO_RAND_PART_C_STATE
|
54
|
+
setup_no_rand_part_c
|
55
|
+
|
56
|
+
when RBzip2::START_BLOCK_STATE
|
57
|
+
when RBzip2::RAND_PART_A_STATE
|
58
|
+
when RBzip2::NO_RAND_PART_A_STATE
|
59
|
+
else
|
60
|
+
raise 'illegal state'
|
61
|
+
end
|
62
|
+
|
63
|
+
ret_char
|
64
|
+
end
|
65
|
+
|
66
|
+
def make_maps
|
67
|
+
in_use = @data.in_use
|
68
|
+
seq_to_unseq = @data.seq_to_unseq;
|
69
|
+
|
70
|
+
n_in_use_shadow = 0;
|
71
|
+
|
72
|
+
256.times do |i|
|
73
|
+
if in_use[i]
|
74
|
+
seq_to_unseq[n_in_use_shadow] = i
|
75
|
+
n_in_use_shadow += 1
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
@n_in_use = n_in_use_shadow;
|
80
|
+
end
|
81
|
+
|
82
|
+
def init
|
83
|
+
check_magic
|
84
|
+
|
85
|
+
block_size = @io.read(1).to_i
|
86
|
+
raise 'Illegal block size.' if block_size < 1 || block_size > 9
|
87
|
+
@block_size = block_size
|
88
|
+
|
89
|
+
init_block
|
90
|
+
setup_block
|
91
|
+
end
|
92
|
+
|
93
|
+
def check_magic
|
94
|
+
raise 'Magic number does not match "BZh".' unless @io.read(3) == 'BZh'
|
95
|
+
end
|
96
|
+
|
97
|
+
def init_block
|
98
|
+
magic = [ubyte, ubyte, ubyte, ubyte, ubyte, ubyte]
|
99
|
+
|
100
|
+
if magic == [0x17, 0x72, 0x45, 0x38, 0x50, 0x90]
|
101
|
+
complete
|
102
|
+
elsif magic != [0x31, 0x41, 0x59, 0x26, 0x53, 0x59]
|
103
|
+
@current_state = RBzip2::EOF
|
104
|
+
|
105
|
+
raise 'Bad block header.'
|
106
|
+
else
|
107
|
+
@stored_block_crc = int
|
108
|
+
@block_randomised = bit
|
109
|
+
|
110
|
+
@data = RBzip2::Data.new @block_size if @data.nil?
|
111
|
+
|
112
|
+
get_and_move_to_front_decode
|
113
|
+
|
114
|
+
@crc.initialize_crc
|
115
|
+
@current_state = RBzip2::START_BLOCK_STATE
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def end_block
|
120
|
+
@computed_block_crc = @crc.final_crc
|
121
|
+
|
122
|
+
if @stored_block_crc != @computed_block_crc
|
123
|
+
@computed_combined_crc = (@stored_combined_crc << 1) | (@stored_combined_crc >> 31)
|
124
|
+
@computed_combined_crc ^= @stored_block_crc
|
125
|
+
|
126
|
+
raise 'BZip2 CRC error'
|
127
|
+
end
|
128
|
+
|
129
|
+
@computed_combined_crc = (@computed_combined_crc << 1) | (@computed_combined_crc >> 31)
|
130
|
+
@computed_combined_crc ^= @computed_block_crc
|
131
|
+
end
|
132
|
+
|
133
|
+
def complete
|
134
|
+
@stored_combined_crc = int
|
135
|
+
@current_state = RBzip2::EOF
|
136
|
+
@data = nil
|
137
|
+
|
138
|
+
raise 'BZip2 CRC error' if @stored_combined_crc != @computed_combined_crc
|
139
|
+
end
|
140
|
+
|
141
|
+
def close
|
142
|
+
if @io != $stdin
|
143
|
+
@io = nil
|
144
|
+
@data = nil
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
def r(n)
|
149
|
+
live_shadow = @live
|
150
|
+
buff_shadow = @buff
|
151
|
+
|
152
|
+
if live_shadow < n
|
153
|
+
begin
|
154
|
+
thech = @io.read(1)[0].ord
|
155
|
+
|
156
|
+
raise 'unexpected end of stream' if thech < 0
|
157
|
+
|
158
|
+
buff_shadow = (buff_shadow << 8) | thech
|
159
|
+
live_shadow += 8
|
160
|
+
end while live_shadow < n
|
161
|
+
|
162
|
+
@buff = buff_shadow
|
163
|
+
end
|
164
|
+
|
165
|
+
@live = live_shadow - n
|
166
|
+
|
167
|
+
(buff_shadow >> (live_shadow - n)) & ((1 << n) - 1)
|
168
|
+
end
|
169
|
+
|
170
|
+
def bit
|
171
|
+
r(1) != 0
|
172
|
+
end
|
173
|
+
|
174
|
+
def ubyte
|
175
|
+
r 8
|
176
|
+
end
|
177
|
+
|
178
|
+
def int
|
179
|
+
(((((r(8) << 8) | r(8)) << 8) | r(8)) << 8) | r(8)
|
180
|
+
end
|
181
|
+
|
182
|
+
def create_decode_tables(limit, base, perm, length, min_len, max_len, alpha_size)
|
183
|
+
pp = 0
|
184
|
+
(min_len..max_len).each do |i|
|
185
|
+
alpha_size.times do |j|
|
186
|
+
if length[j] == i
|
187
|
+
perm[pp] = j
|
188
|
+
pp += 1
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
RBzip2::MAX_CODE_LEN.downto 1 do |i|
|
194
|
+
base[i] = 0
|
195
|
+
limit[i] = 0
|
196
|
+
end
|
197
|
+
|
198
|
+
alpha_size.times do |i|
|
199
|
+
base[length[i] + 1] += 1
|
200
|
+
end
|
201
|
+
|
202
|
+
b = 0
|
203
|
+
1.upto(RBzip2::MAX_CODE_LEN - 1) do |i|
|
204
|
+
b += base[i]
|
205
|
+
base[i] = b
|
206
|
+
end
|
207
|
+
|
208
|
+
vec = 0
|
209
|
+
min_len.upto(max_len) do |i|
|
210
|
+
b = base[i]
|
211
|
+
nb = base[i + 1]
|
212
|
+
vec += nb - b
|
213
|
+
b = nb
|
214
|
+
limit[i] = vec -1
|
215
|
+
vec = vec << 1
|
216
|
+
end
|
217
|
+
|
218
|
+
(min_len + 1).upto(max_len) do |i|
|
219
|
+
base[i] = ((limit[i - 1] + 1) << 1) - base[i]
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
def receive_decoding_tables
|
224
|
+
in_use = @data.in_use
|
225
|
+
pos = @data.receive_decoding_tables_pos
|
226
|
+
selector = @data.selector
|
227
|
+
selector_mtf = @data.selector_mtf
|
228
|
+
|
229
|
+
in_use16 = 0
|
230
|
+
|
231
|
+
16.times do |i|
|
232
|
+
in_use16 |= 1 << i if bit
|
233
|
+
end
|
234
|
+
|
235
|
+
255.downto(0) do |i|
|
236
|
+
in_use[i] = false
|
237
|
+
end
|
238
|
+
|
239
|
+
16.times do |i|
|
240
|
+
if (in_use16 & (1 << i)) != 0
|
241
|
+
i16 = i << 4
|
242
|
+
16.times do |j|
|
243
|
+
in_use[i16 + j] = true if bit
|
244
|
+
end
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
make_maps
|
249
|
+
alpha_size = @n_in_use + 2
|
250
|
+
|
251
|
+
groups = r 3
|
252
|
+
selectors = r 15
|
253
|
+
|
254
|
+
selectors.times do |i|
|
255
|
+
j = 0
|
256
|
+
while bit
|
257
|
+
j += 1
|
258
|
+
end
|
259
|
+
selector_mtf[i] = j
|
260
|
+
end
|
261
|
+
|
262
|
+
groups.downto(0) do |v|
|
263
|
+
pos[v] = v
|
264
|
+
end
|
265
|
+
|
266
|
+
selectors.times do |i|
|
267
|
+
v = selector_mtf[i] & 0xff
|
268
|
+
tmp = pos[v]
|
269
|
+
|
270
|
+
while v > 0 do
|
271
|
+
pos[v] = pos[v -= 1]
|
272
|
+
end
|
273
|
+
|
274
|
+
pos[0] = tmp
|
275
|
+
selector[i] = tmp
|
276
|
+
end
|
277
|
+
|
278
|
+
len = @data.temp_char_array_2d
|
279
|
+
|
280
|
+
groups.times do |t|
|
281
|
+
curr = r 5
|
282
|
+
len_t = len[t]
|
283
|
+
alpha_size.times do |i|
|
284
|
+
while bit
|
285
|
+
curr += bit ? -1 : 1
|
286
|
+
end
|
287
|
+
len_t[i] = curr
|
288
|
+
end
|
289
|
+
@data.temp_char_array_2d[t] = len_t
|
290
|
+
end
|
291
|
+
|
292
|
+
create_huffman_decoding_tables alpha_size, groups
|
293
|
+
end
|
294
|
+
|
295
|
+
def create_huffman_decoding_tables(alpha_size, groups)
|
296
|
+
len = @data.temp_char_array_2d
|
297
|
+
min_lens = @data.min_lens
|
298
|
+
limit = @data.limit
|
299
|
+
base = @data.base
|
300
|
+
perm = @data.perm
|
301
|
+
|
302
|
+
groups.times do |t|
|
303
|
+
min_len = 32
|
304
|
+
max_len = 0
|
305
|
+
len_t = len[t]
|
306
|
+
|
307
|
+
(alpha_size - 1).downto 0 do |i|
|
308
|
+
lent = len_t[i]
|
309
|
+
max_len = lent if lent > max_len
|
310
|
+
min_len = lent if lent < min_len
|
311
|
+
end
|
312
|
+
|
313
|
+
create_decode_tables limit[t], base[t], perm[t], len[t], min_len, max_len, alpha_size
|
314
|
+
min_lens[t] = min_len
|
315
|
+
end
|
316
|
+
end
|
317
|
+
|
318
|
+
def get_and_move_to_front_decode
|
319
|
+
@orig_ptr = r 24
|
320
|
+
receive_decoding_tables
|
321
|
+
|
322
|
+
ll8 = @data.ll8
|
323
|
+
unzftab = @data.unzftab
|
324
|
+
selector = @data.selector
|
325
|
+
seq_to_unseq = @data.seq_to_unseq
|
326
|
+
yy = @data.get_and_move_to_front_decode_yy
|
327
|
+
min_lens = @data.min_lens
|
328
|
+
limit = @data.limit
|
329
|
+
base = @data.base
|
330
|
+
perm = @data.perm
|
331
|
+
limit_last = @block_size * RBzip2::BASEBLOCKSIZE
|
332
|
+
|
333
|
+
256.downto(0) do |i|
|
334
|
+
yy[i] = i
|
335
|
+
unzftab[i] = 0
|
336
|
+
end
|
337
|
+
|
338
|
+
group_no = 0
|
339
|
+
group_pos = RBzip2::G_SIZE - 1
|
340
|
+
eob = @n_in_use + 1
|
341
|
+
next_sym = get_and_move_to_front_decode0 0
|
342
|
+
buff_shadow = @buff
|
343
|
+
live_shadow = @live
|
344
|
+
last_shadow = -1
|
345
|
+
zt = selector[group_no] & 0xff
|
346
|
+
base_zt = base[zt]
|
347
|
+
limit_zt = limit[zt]
|
348
|
+
perm_zt = perm[zt]
|
349
|
+
min_lens_zt = min_lens[zt]
|
350
|
+
|
351
|
+
while next_sym != eob
|
352
|
+
if (next_sym == RBzip2::RUNA) || (next_sym == RBzip2::RUNB)
|
353
|
+
s = -1
|
354
|
+
|
355
|
+
n = 1
|
356
|
+
loop do
|
357
|
+
if next_sym == RBzip2::RUNA
|
358
|
+
s += n
|
359
|
+
elsif next_sym == RBzip2::RUNB
|
360
|
+
s += n << 1
|
361
|
+
else
|
362
|
+
break
|
363
|
+
end
|
364
|
+
|
365
|
+
if group_pos == 0
|
366
|
+
group_pos = RBzip2::G_SIZE - 1
|
367
|
+
group_no += 1
|
368
|
+
zt = selector[group_no] & 0xff
|
369
|
+
base_zt = base[zt]
|
370
|
+
limit_zt = limit[zt]
|
371
|
+
perm_zt = perm[zt]
|
372
|
+
min_lens_zt = min_lens[zt]
|
373
|
+
else
|
374
|
+
group_pos -= 1
|
375
|
+
end
|
376
|
+
|
377
|
+
zn = min_lens_zt
|
378
|
+
|
379
|
+
while live_shadow < zn
|
380
|
+
thech = @io.read(1)[0].ord
|
381
|
+
|
382
|
+
raise 'unexpected end of stream' if thech < 0
|
383
|
+
|
384
|
+
buff_shadow = (buff_shadow << 8) | thech
|
385
|
+
live_shadow += 8
|
386
|
+
end
|
387
|
+
|
388
|
+
zvec = (buff_shadow >> (live_shadow - zn)) & ((1 << zn) - 1)
|
389
|
+
live_shadow -= zn
|
390
|
+
|
391
|
+
while zvec > limit_zt[zn]
|
392
|
+
zn += 1
|
393
|
+
|
394
|
+
while live_shadow < 1
|
395
|
+
thech = @io.read(1)[0].ord
|
396
|
+
|
397
|
+
raise 'unexpected end of stream' if thech < 0
|
398
|
+
|
399
|
+
buff_shadow = (buff_shadow << 8) | thech
|
400
|
+
live_shadow += 8
|
401
|
+
end
|
402
|
+
|
403
|
+
live_shadow -= 1
|
404
|
+
zvec = (zvec << 1) | ((buff_shadow >> live_shadow) & 1)
|
405
|
+
end
|
406
|
+
|
407
|
+
next_sym = perm_zt[zvec - base_zt[zn]]
|
408
|
+
|
409
|
+
n = n << 1
|
410
|
+
end
|
411
|
+
|
412
|
+
ch = seq_to_unseq[yy[0]]
|
413
|
+
unzftab[ch & 0xff] += s + 1
|
414
|
+
|
415
|
+
while s >= 0
|
416
|
+
last_shadow += 1
|
417
|
+
ll8[last_shadow] = ch
|
418
|
+
s -= 1
|
419
|
+
end
|
420
|
+
|
421
|
+
raise 'block overrun' if last_shadow >= limit_last
|
422
|
+
else
|
423
|
+
last_shadow += 1
|
424
|
+
raise 'block overrun' if last_shadow >= limit_last
|
425
|
+
|
426
|
+
tmp = yy[next_sym - 1]
|
427
|
+
unzftab[seq_to_unseq[tmp] & 0xff] += 1
|
428
|
+
ll8[last_shadow] = seq_to_unseq[tmp]
|
429
|
+
|
430
|
+
yy[1, next_sym - 1] = yy[0, next_sym - 1]
|
431
|
+
yy[0] = tmp
|
432
|
+
|
433
|
+
if group_pos == 0
|
434
|
+
group_pos = RBzip2::G_SIZE - 1
|
435
|
+
group_no += 1
|
436
|
+
zt = selector[group_no] & 0xff
|
437
|
+
base_zt = base[zt]
|
438
|
+
limit_zt = limit[zt]
|
439
|
+
perm_zt = perm[zt]
|
440
|
+
min_lens_zt = min_lens[zt]
|
441
|
+
else
|
442
|
+
group_pos -= 1
|
443
|
+
end
|
444
|
+
|
445
|
+
zn = min_lens_zt
|
446
|
+
|
447
|
+
while live_shadow < zn
|
448
|
+
thech = @io.read(1)[0].ord
|
449
|
+
|
450
|
+
raise 'unexpected end of stream' if thech < 0
|
451
|
+
|
452
|
+
buff_shadow = (buff_shadow << 8) | thech
|
453
|
+
live_shadow += 8
|
454
|
+
end
|
455
|
+
zvec = (buff_shadow >> (live_shadow - zn)) & ((1 << zn) - 1)
|
456
|
+
live_shadow -= zn
|
457
|
+
|
458
|
+
while zvec > limit_zt[zn]
|
459
|
+
zn += 1
|
460
|
+
while live_shadow < 1
|
461
|
+
thech = @io.read(1)[0].ord
|
462
|
+
|
463
|
+
raise 'unexpected end of stream' if thech < 0
|
464
|
+
|
465
|
+
buff_shadow = (buff_shadow << 8) | thech
|
466
|
+
live_shadow += 8
|
467
|
+
end
|
468
|
+
live_shadow -= 1
|
469
|
+
zvec = (zvec << 1) | ((buff_shadow >> live_shadow) & 1)
|
470
|
+
end
|
471
|
+
|
472
|
+
next_sym = perm_zt[zvec - base_zt[zn]]
|
473
|
+
end
|
474
|
+
end
|
475
|
+
|
476
|
+
@last = last_shadow
|
477
|
+
@live = live_shadow
|
478
|
+
@buff = buff_shadow
|
479
|
+
end
|
480
|
+
|
481
|
+
def get_and_move_to_front_decode0(group_no)
|
482
|
+
zt = @data.selector[group_no] & 0xff
|
483
|
+
limit_zt = @data.limit[zt]
|
484
|
+
zn = @data.min_lens[zt]
|
485
|
+
zvec = r zn
|
486
|
+
live_shadow = @live
|
487
|
+
buff_shadow = @buff
|
488
|
+
|
489
|
+
while zvec > limit_zt[zn]
|
490
|
+
zn += 1
|
491
|
+
|
492
|
+
while live_shadow < 1
|
493
|
+
thech = @io.read(1)[0].ord
|
494
|
+
|
495
|
+
raise 'unexpected end of stream' if thech < 0
|
496
|
+
|
497
|
+
buff_shadow = (buff_shadow << 8) | thech
|
498
|
+
live_shadow += 8
|
499
|
+
end
|
500
|
+
|
501
|
+
live_shadow -=1
|
502
|
+
zvec = (zvec << 1) | ((buff_shadow >> live_shadow) & 1)
|
503
|
+
end
|
504
|
+
|
505
|
+
@live = live_shadow
|
506
|
+
@buff = buff_shadow
|
507
|
+
|
508
|
+
@data.perm[zt][zvec - @data.base[zt][zn]]
|
509
|
+
end
|
510
|
+
|
511
|
+
def setup_block
|
512
|
+
return if @data.nil?
|
513
|
+
|
514
|
+
cftab = @data.cftab
|
515
|
+
tt = @data.init_tt @last + 1
|
516
|
+
ll8 = @data.ll8
|
517
|
+
cftab[0] = 0
|
518
|
+
cftab[1, 256] = @data.unzftab[0, 256]
|
519
|
+
|
520
|
+
c = cftab[0]
|
521
|
+
1.upto(256) do |i|
|
522
|
+
c += cftab[i]
|
523
|
+
cftab[i] = c
|
524
|
+
end
|
525
|
+
|
526
|
+
last_shadow = @last
|
527
|
+
(last_shadow + 1).times do |i|
|
528
|
+
cftab_i = ll8[i] & 0xff
|
529
|
+
tt[cftab[cftab_i]] = i
|
530
|
+
cftab[cftab_i] += 1
|
531
|
+
end
|
532
|
+
|
533
|
+
raise 'stream corrupted' if @orig_ptr < 0 || @orig_ptr >= tt.size
|
534
|
+
|
535
|
+
@su_t_pos = tt[@orig_ptr]
|
536
|
+
@su_count = 0
|
537
|
+
@su_i2 = 0
|
538
|
+
@su_ch2 = 256
|
539
|
+
|
540
|
+
if @block_randomised
|
541
|
+
@su_r_n_to_go = 0
|
542
|
+
@su_r_t_pos = 0
|
543
|
+
|
544
|
+
setup_rand_part_a
|
545
|
+
else
|
546
|
+
setup_no_rand_part_a
|
547
|
+
end
|
548
|
+
end
|
549
|
+
|
550
|
+
def setup_rand_part_a
|
551
|
+
if @su_i2 <= @last
|
552
|
+
@su_ch_prev = @su_ch2
|
553
|
+
su_ch2_shadow = @data.ll8[@su_t_pos] & 0xff
|
554
|
+
@su_t_pos = @data.tt[@su_t_pos]
|
555
|
+
|
556
|
+
if @su_r_n_to_go == 0
|
557
|
+
@su_r_n_to_go = RBzip2::RNUMS[@su_r_t_pos] - 1
|
558
|
+
@su_r_t_pos += 1
|
559
|
+
@su_r_t_pos = 0 if @su_r_t_pos == 512
|
560
|
+
else
|
561
|
+
@su_r_n_to_go -= 1
|
562
|
+
end
|
563
|
+
|
564
|
+
@su_ch2 = su_ch2_shadow ^= (@su_r_n_to_go == 1) ? 1 : 0
|
565
|
+
@su_i2 += 1
|
566
|
+
@current_char = su_ch2_shadow
|
567
|
+
@current_state = RBzip2::RAND_PART_B_STATE
|
568
|
+
@crc.update_crc su_ch2_shadow
|
569
|
+
else
|
570
|
+
end_block
|
571
|
+
init_block
|
572
|
+
setup_block
|
573
|
+
end
|
574
|
+
end
|
575
|
+
|
576
|
+
def setup_no_rand_part_a
|
577
|
+
if @su_i2 <= @last
|
578
|
+
@su_ch_prev = @su_ch2
|
579
|
+
su_ch2_shadow = @data.ll8[@su_t_pos] & 0xff
|
580
|
+
@su_ch2 = su_ch2_shadow
|
581
|
+
@su_t_pos = @data.tt[@su_t_pos]
|
582
|
+
@su_i2 += 1
|
583
|
+
@current_char = su_ch2_shadow
|
584
|
+
@current_state = RBzip2::NO_RAND_PART_B_STATE
|
585
|
+
@crc.update_crc su_ch2_shadow
|
586
|
+
else
|
587
|
+
@current_state = RBzip2::NO_RAND_PART_A_STATE
|
588
|
+
end_block
|
589
|
+
init_block
|
590
|
+
setup_block
|
591
|
+
end
|
592
|
+
end
|
593
|
+
|
594
|
+
def setup_rand_part_b
|
595
|
+
if @su_ch2 != @su_ch_prev
|
596
|
+
@current_state = RBzip2::RAND_PART_A_STATE
|
597
|
+
@su_count = 1
|
598
|
+
setup_rand_part_a
|
599
|
+
else
|
600
|
+
@su_count += 1
|
601
|
+
if @su_count >= 4
|
602
|
+
@su_z = @data.ll8[@su_t_pos] & 0xff
|
603
|
+
@su_t_pos = @data.tt[@su_t_pos]
|
604
|
+
|
605
|
+
if @su_r_n_to_go == 0
|
606
|
+
@su_r_n_to_go = RBzip2::RNUMS[@su_r_t_pos] - 1
|
607
|
+
@su_r_t_pos += 1
|
608
|
+
@su_r_t_pos = 0 if @su_r_t_pos == 512
|
609
|
+
else
|
610
|
+
@su_r_n_to_go -= 1
|
611
|
+
end
|
612
|
+
|
613
|
+
@su_j2 = 0
|
614
|
+
@current_state = RBzip2::RAND_PART_C_STATE
|
615
|
+
@su_z ^= 1 if @su_r_n_to_go == 1
|
616
|
+
setup_rand_part_c
|
617
|
+
else
|
618
|
+
@current_state = RBzip2::RAND_PART_A_STATE
|
619
|
+
setup_rand_part_a
|
620
|
+
end
|
621
|
+
end
|
622
|
+
end
|
623
|
+
|
624
|
+
def setup_rand_part_c
|
625
|
+
if @su_j2 < @su_z
|
626
|
+
@current_char = @su_ch2
|
627
|
+
@crc.update_crc @su_ch2
|
628
|
+
@su_j2 += 1
|
629
|
+
else
|
630
|
+
@current_state = RBzip2::RAND_PART_A_STATE
|
631
|
+
@su_i2 += 1
|
632
|
+
@su_count = 0
|
633
|
+
setup_rand_part_a
|
634
|
+
end
|
635
|
+
end
|
636
|
+
|
637
|
+
def setup_no_rand_part_b
|
638
|
+
if @su_ch2 != @su_ch_prev
|
639
|
+
@su_count = 1
|
640
|
+
setup_no_rand_part_a
|
641
|
+
else
|
642
|
+
@su_count += 1
|
643
|
+
if @su_count >= 4
|
644
|
+
@su_z = @data.ll8[@su_t_pos] & 0xff
|
645
|
+
@su_t_pos = @data.tt[@su_t_pos]
|
646
|
+
@su_j2 = 0
|
647
|
+
setup_no_rand_part_c
|
648
|
+
else
|
649
|
+
setup_no_rand_part_a
|
650
|
+
end
|
651
|
+
end
|
652
|
+
end
|
653
|
+
|
654
|
+
def setup_no_rand_part_c
|
655
|
+
if @su_j2 < @su_z
|
656
|
+
su_ch2_shadow = @su_ch2
|
657
|
+
@current_char = su_ch2_shadow
|
658
|
+
@crc.update_crc su_ch2_shadow
|
659
|
+
@su_j2 += 1
|
660
|
+
@current_state = RBzip2::NO_RAND_PART_C_STATE
|
661
|
+
else
|
662
|
+
@su_i2 += 1
|
663
|
+
@su_count = 0
|
664
|
+
setup_no_rand_part_a
|
665
|
+
end
|
666
|
+
end
|
667
|
+
|
668
|
+
def size
|
669
|
+
if @io.is_a? StringIO
|
670
|
+
@io.size
|
671
|
+
elsif @io.is_a? File
|
672
|
+
@io.stat.size
|
673
|
+
end
|
674
|
+
end
|
675
|
+
|
676
|
+
def uncompressed
|
677
|
+
@last + 1
|
678
|
+
end
|
679
|
+
|
680
|
+
def inspect
|
681
|
+
"#<#{self.class}: @io=#{@io.inspect} size=#{size} uncompressed=#{uncompressed}>"
|
682
|
+
end
|
683
|
+
|
684
|
+
end
|
data/lib/rbzip2/io.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# This code is free software; you can redistribute it and/or modify it under
|
2
|
+
# the terms of the new BSD License.
|
3
|
+
#
|
4
|
+
# Copyright (c) 2011, Sebastian Staudt
|
5
|
+
|
6
|
+
require 'rbzip2/decompressor'
|
7
|
+
|
8
|
+
class RBzip2::IO
|
9
|
+
|
10
|
+
include RBzip2::Decompressor
|
11
|
+
|
12
|
+
def initialize(io)
|
13
|
+
@buff = 0
|
14
|
+
@bytes_read = 0
|
15
|
+
@computed_combined_crc = 0
|
16
|
+
@crc = RBzip2::CRC.new
|
17
|
+
@current_char = -1
|
18
|
+
@io = io
|
19
|
+
@live = 0
|
20
|
+
@stored_combined_crc = 0
|
21
|
+
@su_t_pos = 0
|
22
|
+
init
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
data/lib/rbzip2.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
# This code is free software; you can redistribute it and/or modify it under
|
2
|
+
# the terms of the new BSD License.
|
3
|
+
#
|
4
|
+
# Copyright (c) 2011, Sebastian Staudt
|
5
|
+
|
6
|
+
module RBzip2
|
7
|
+
|
8
|
+
autoload :CRC, 'rbzip2/crc'
|
9
|
+
autoload :Data, 'rbzip2/data'
|
10
|
+
autoload :Decompressor, 'rbzip2/decompressor'
|
11
|
+
autoload :IO, 'rbzip2/io'
|
12
|
+
autoload :VERSION, 'rbzip2/version'
|
13
|
+
|
14
|
+
end
|
data/rbzip2.gemspec
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# This code is free software; you can redistribute it and/or modify it under
|
2
|
+
# the terms of the new BSD License.
|
3
|
+
#
|
4
|
+
# Copyright (c) 2011, Sebastian Staudt
|
5
|
+
|
6
|
+
require File.expand_path(File.dirname(__FILE__) + '/lib/rbzip2/version')
|
7
|
+
|
8
|
+
Gem::Specification.new do |s|
|
9
|
+
s.name = 'rbzip2'
|
10
|
+
s.version = RBzip2::VERSION
|
11
|
+
s.platform = Gem::Platform::RUBY
|
12
|
+
s.authors = [ 'Sebastian Staudt' ]
|
13
|
+
s.email = [ 'koraktor@gmail.com' ]
|
14
|
+
s.homepage = 'https://github.com/koraktor/rbzip2'
|
15
|
+
s.summary = 'Pure Ruby impementation of bzip2'
|
16
|
+
s.description = 'A pure Ruby implementation of the bzip2 compression algorithm.'
|
17
|
+
|
18
|
+
s.add_development_dependency 'mocha', '~> 0.10.0'
|
19
|
+
s.add_development_dependency 'rake', '~> 0.9.2'
|
20
|
+
s.add_development_dependency 'rspec-core', '~> 2.7.1'
|
21
|
+
s.add_development_dependency 'rspec-expectations', '~> 2.7.0'
|
22
|
+
s.add_development_dependency 'yard', '~> 0.7.3'
|
23
|
+
|
24
|
+
s.files = `git ls-files`.split("\n")
|
25
|
+
s.test_files = `git ls-files -- spec/*`.split("\n")
|
26
|
+
s.require_paths = [ 'lib' ]
|
27
|
+
end
|
Binary file
|
@@ -0,0 +1,11 @@
|
|
1
|
+
This is a test fixture for RBzip2.
|
2
|
+
Its contents will be compressed and decompressed to test the functionality.
|
3
|
+
|
4
|
+
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod
|
5
|
+
tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At
|
6
|
+
vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd
|
7
|
+
gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum
|
8
|
+
dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor
|
9
|
+
invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero
|
10
|
+
eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no
|
11
|
+
sea takimata sanctus est Lorem ipsum dolor sit amet.
|
data/spec/helper.rb
ADDED
data/spec/io_spec.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
# This code is free software; you can redistribute it and/or modify it under
|
2
|
+
# the terms of the new BSD License.
|
3
|
+
#
|
4
|
+
# Copyright (c) 2011, Sebastian Staudt
|
5
|
+
|
6
|
+
require 'helper'
|
7
|
+
|
8
|
+
describe RBzip2::IO do
|
9
|
+
|
10
|
+
before do
|
11
|
+
@txt_file = File.new File.join(File.dirname(__FILE__), 'fixtures/test.txt')
|
12
|
+
bz2_file = File.new File.join(File.dirname(__FILE__), 'fixtures/test.bz2')
|
13
|
+
@bz2_io = RBzip2::IO.new bz2_file
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'allows decompressing data' do
|
17
|
+
RBzip2::IO.should include(Decompressor)
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'acts like a standard IO' do
|
21
|
+
methods = RBzip2::IO.instance_methods.map { |m| m.to_sym }
|
22
|
+
methods.should include(:read, :close)
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'knows its size' do
|
26
|
+
@bz2_io.size.should be(375)
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'knows the size of the uncompressed data' do
|
30
|
+
@bz2_io.uncompressed.should be(704)
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'should be able to decompress compressed data' do
|
34
|
+
@bz2_io.read.should eq(@txt_file.read)
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
metadata
ADDED
@@ -0,0 +1,166 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rbzip2
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 27
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
- 0
|
10
|
+
version: 0.1.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Sebastian Staudt
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-11-09 00:00:00 Z
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
type: :development
|
22
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
23
|
+
none: false
|
24
|
+
requirements:
|
25
|
+
- - ~>
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
hash: 55
|
28
|
+
segments:
|
29
|
+
- 0
|
30
|
+
- 10
|
31
|
+
- 0
|
32
|
+
version: 0.10.0
|
33
|
+
prerelease: false
|
34
|
+
name: mocha
|
35
|
+
version_requirements: *id001
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
type: :development
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ~>
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
hash: 63
|
44
|
+
segments:
|
45
|
+
- 0
|
46
|
+
- 9
|
47
|
+
- 2
|
48
|
+
version: 0.9.2
|
49
|
+
prerelease: false
|
50
|
+
name: rake
|
51
|
+
version_requirements: *id002
|
52
|
+
- !ruby/object:Gem::Dependency
|
53
|
+
type: :development
|
54
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
55
|
+
none: false
|
56
|
+
requirements:
|
57
|
+
- - ~>
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
hash: 17
|
60
|
+
segments:
|
61
|
+
- 2
|
62
|
+
- 7
|
63
|
+
- 1
|
64
|
+
version: 2.7.1
|
65
|
+
prerelease: false
|
66
|
+
name: rspec-core
|
67
|
+
version_requirements: *id003
|
68
|
+
- !ruby/object:Gem::Dependency
|
69
|
+
type: :development
|
70
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
71
|
+
none: false
|
72
|
+
requirements:
|
73
|
+
- - ~>
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
hash: 19
|
76
|
+
segments:
|
77
|
+
- 2
|
78
|
+
- 7
|
79
|
+
- 0
|
80
|
+
version: 2.7.0
|
81
|
+
prerelease: false
|
82
|
+
name: rspec-expectations
|
83
|
+
version_requirements: *id004
|
84
|
+
- !ruby/object:Gem::Dependency
|
85
|
+
type: :development
|
86
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
87
|
+
none: false
|
88
|
+
requirements:
|
89
|
+
- - ~>
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
hash: 5
|
92
|
+
segments:
|
93
|
+
- 0
|
94
|
+
- 7
|
95
|
+
- 3
|
96
|
+
version: 0.7.3
|
97
|
+
prerelease: false
|
98
|
+
name: yard
|
99
|
+
version_requirements: *id005
|
100
|
+
description: A pure Ruby implementation of the bzip2 compression algorithm.
|
101
|
+
email:
|
102
|
+
- koraktor@gmail.com
|
103
|
+
executables: []
|
104
|
+
|
105
|
+
extensions: []
|
106
|
+
|
107
|
+
extra_rdoc_files: []
|
108
|
+
|
109
|
+
files:
|
110
|
+
- .gitignore
|
111
|
+
- .travis.yml
|
112
|
+
- Gemfile
|
113
|
+
- Gemfile.lock
|
114
|
+
- LICENSE
|
115
|
+
- README.md
|
116
|
+
- Rakefile
|
117
|
+
- lib/rbzip2.rb
|
118
|
+
- lib/rbzip2/constants.rb
|
119
|
+
- lib/rbzip2/crc.rb
|
120
|
+
- lib/rbzip2/data.rb
|
121
|
+
- lib/rbzip2/decompressor.rb
|
122
|
+
- lib/rbzip2/io.rb
|
123
|
+
- lib/rbzip2/version.rb
|
124
|
+
- rbzip2.gemspec
|
125
|
+
- spec/fixtures/test.bz2
|
126
|
+
- spec/fixtures/test.txt
|
127
|
+
- spec/helper.rb
|
128
|
+
- spec/io_spec.rb
|
129
|
+
homepage: https://github.com/koraktor/rbzip2
|
130
|
+
licenses: []
|
131
|
+
|
132
|
+
post_install_message:
|
133
|
+
rdoc_options: []
|
134
|
+
|
135
|
+
require_paths:
|
136
|
+
- lib
|
137
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
138
|
+
none: false
|
139
|
+
requirements:
|
140
|
+
- - ">="
|
141
|
+
- !ruby/object:Gem::Version
|
142
|
+
hash: 3
|
143
|
+
segments:
|
144
|
+
- 0
|
145
|
+
version: "0"
|
146
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
147
|
+
none: false
|
148
|
+
requirements:
|
149
|
+
- - ">="
|
150
|
+
- !ruby/object:Gem::Version
|
151
|
+
hash: 3
|
152
|
+
segments:
|
153
|
+
- 0
|
154
|
+
version: "0"
|
155
|
+
requirements: []
|
156
|
+
|
157
|
+
rubyforge_project:
|
158
|
+
rubygems_version: 1.8.11
|
159
|
+
signing_key:
|
160
|
+
specification_version: 3
|
161
|
+
summary: Pure Ruby impementation of bzip2
|
162
|
+
test_files:
|
163
|
+
- spec/fixtures/test.bz2
|
164
|
+
- spec/fixtures/test.txt
|
165
|
+
- spec/helper.rb
|
166
|
+
- spec/io_spec.rb
|