zippo 0.2.0 → 0.2.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.
- checksums.yaml +6 -14
- data/.rubocop.yml +35 -0
- data/.travis.yml +3 -0
- data/README.md +4 -0
- data/Rakefile +8 -2
- data/lib/zippo.rb +1 -1
- data/lib/zippo/binary_structure/base.rb +10 -8
- data/lib/zippo/binary_structure/binary_packer.rb +2 -2
- data/lib/zippo/binary_structure/meta.rb +9 -11
- data/lib/zippo/binary_structure/structure.rb +6 -4
- data/lib/zippo/binary_structure/structure_member.rb +1 -1
- data/lib/zippo/cd_file_header.rb +14 -14
- data/lib/zippo/central_directory_entries_unpacker.rb +3 -2
- data/lib/zippo/central_directory_reader.rb +4 -3
- data/lib/zippo/end_cd_record.rb +6 -6
- data/lib/zippo/filter/base.rb +3 -2
- data/lib/zippo/filter/compressor.rb +4 -4
- data/lib/zippo/filter/compressor/deflate.rb +1 -0
- data/lib/zippo/filter/null_filters.rb +1 -0
- data/lib/zippo/filter/uncompressor.rb +3 -5
- data/lib/zippo/filter/uncompressor/deflate.rb +1 -0
- data/lib/zippo/io_zip_member.rb +1 -1
- data/lib/zippo/local_file_header.rb +8 -8
- data/lib/zippo/version.rb +1 -1
- data/lib/zippo/zip_directory.rb +15 -12
- data/lib/zippo/zip_file.rb +8 -6
- data/lib/zippo/zip_file_writer.rb +4 -4
- data/lib/zippo/zip_member.rb +4 -3
- data/spec/binary_structure_spec.rb +26 -28
- data/spec/central_directory_entries_unpacker_spec.rb +2 -3
- data/spec/central_directory_parser_spec.rb +4 -4
- data/spec/central_directory_unpacker_spec.rb +0 -1
- data/spec/deflate_compressor_spec.rb +4 -4
- data/spec/deflate_uncompressor_spec.rb +5 -6
- data/spec/integration/compressors_spec.rb +1 -1
- data/spec/integration/zippo_spec.rb +4 -3
- data/spec/spec_helper.rb +9 -0
- data/spec/store_compressor_spec.rb +3 -3
- data/spec/store_uncompressor_spec.rb +1 -1
- data/spec/zip_directory_spec.rb +15 -15
- data/spec/zip_file_spec.rb +1 -1
- data/spec/zip_file_writer_spec.rb +0 -1
- data/spec/zip_member_spec.rb +4 -6
- data/yard_extensions.rb +1 -1
- data/zippo.gemspec +7 -6
- metadata +59 -19
checksums.yaml
CHANGED
@@ -1,15 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
metadata.gz: !binary |-
|
9
|
-
NjI5ZDU5MTdiMWU0ZDc5NjBhNzMwMWY2YTRkNzYyZDRjZDMzNTFmOTcxMWI4
|
10
|
-
NDI3NGYzYWU5ZWQyOTEzYzY5N2U4YzFhNTA1ZWE2NTRlMTEzNTUzYzEyYmIx
|
11
|
-
ZGY4Njc5NjE1YWY5NWI4NjZjM2UxNGMxZTRiZGQ4MTFkZGM0OWU=
|
12
|
-
data.tar.gz: !binary |-
|
13
|
-
YmJkYjQ3YmQ2YWFjNjRhNGZmNWI5MTlhOGMzYjliMjg5MWQ4YzRhZTVhMGY3
|
14
|
-
OGIyZDJiMzM1NDNmMzY5MGVmNjFlZmFhMWM2MDY4ZjVmNDdiYzI4MmE1MDhk
|
15
|
-
N2I5Zjk1YzRlYTIwZWY2NDY5ZDMwYzMyNzEzZGI5NjMzZDFiZDE=
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 40c9371e43e13d46ae694e7ed3bcb0168598a92c
|
4
|
+
data.tar.gz: 035f7bea5022170d7ddd7bcc16cabef3fb3b9ba2
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 3532b3b02c7d4895790e3b4606e69586ae1bc142d184f2cecc9356e3777d56ca58a6008f090491a63633763a121de690e20063a6992ecb1228f09cbab239f19e
|
7
|
+
data.tar.gz: 78a7cef02643a7b12833a1ebf98d3871d5290b0dfb0313cdae73777faba860e8297f02a2f2c055435d875aa6328abca52e10153b1fd165c69b921e49275e31e0
|
data/.rubocop.yml
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
Metrics/LineLength:
|
2
|
+
Max: 164
|
3
|
+
|
4
|
+
Metrics/MethodLength:
|
5
|
+
Max: 31
|
6
|
+
|
7
|
+
Metrics/AbcSize:
|
8
|
+
Max: 46
|
9
|
+
|
10
|
+
Style/StringLiteralsInInterpolation:
|
11
|
+
Enabled: false
|
12
|
+
|
13
|
+
Style/Documentation:
|
14
|
+
Enabled: false
|
15
|
+
|
16
|
+
Style/NumericLiterals:
|
17
|
+
Enabled: false
|
18
|
+
|
19
|
+
Style/StringLiterals:
|
20
|
+
Enabled: false
|
21
|
+
|
22
|
+
Style/ClassAndModuleChildren:
|
23
|
+
Enabled: false
|
24
|
+
|
25
|
+
Style/AndOr:
|
26
|
+
Enabled: false
|
27
|
+
|
28
|
+
Style/MultilineBlockChain:
|
29
|
+
Enabled: false
|
30
|
+
|
31
|
+
Style/TrailingComma:
|
32
|
+
EnforcedStyleForMultiline: comma
|
33
|
+
|
34
|
+
Style/MultilineOperationIndentation:
|
35
|
+
Enabled: false
|
data/.travis.yml
ADDED
data/README.md
CHANGED
@@ -1,7 +1,11 @@
|
|
1
1
|
# Zippo
|
2
2
|
|
3
|
+
[](https://travis-ci.org/JonathonMA/zippo)
|
4
|
+
|
3
5
|
Zippo is a fast zip library for ruby.
|
4
6
|
|
7
|
+
A [benchmark](https://gist.github.com/JonathonMA/7943484) is available.
|
8
|
+
|
5
9
|
## Installation
|
6
10
|
|
7
11
|
Add this line to your application's Gemfile:
|
data/Rakefile
CHANGED
@@ -1,11 +1,17 @@
|
|
1
1
|
#!/usr/bin/env rake
|
2
2
|
require 'bundler/gem_tasks'
|
3
3
|
require 'rspec/core/rake_task'
|
4
|
+
require 'rubocop/rake_task'
|
4
5
|
require 'yard'
|
5
|
-
require './yard_extensions'
|
6
6
|
|
7
|
-
|
7
|
+
require './yard_extensions'
|
8
8
|
|
9
9
|
RSpec::Core::RakeTask.new
|
10
|
+
RuboCop::RakeTask.new
|
10
11
|
|
11
12
|
YARD::Rake::YardocTask.new
|
13
|
+
|
14
|
+
task default: [
|
15
|
+
:spec,
|
16
|
+
:rubocop,
|
17
|
+
]
|
data/lib/zippo.rb
CHANGED
@@ -32,18 +32,18 @@ module Zippo
|
|
32
32
|
# @see Array#pack
|
33
33
|
module BinaryStructure
|
34
34
|
module Base
|
35
|
-
def binary_structure
|
35
|
+
def binary_structure(&block)
|
36
36
|
@structure = Structure.create(self, &block)
|
37
|
-
|
37
|
+
const_set :Packer, Class.new(BinaryPacker)
|
38
38
|
self::Packer.structure = @structure
|
39
|
-
|
39
|
+
const_set :Unpacker, Class.new(BinaryUnpacker)
|
40
40
|
self::Unpacker.structure = @structure
|
41
41
|
|
42
42
|
@structure.fields.each do |field|
|
43
43
|
attr_reader field.name
|
44
44
|
if @structure.dependent? field.name
|
45
|
-
define_method "#{field.name}=" do |
|
46
|
-
|
45
|
+
define_method "#{field.name}=" do |_value|
|
46
|
+
fail "can't mutate a dependent field"
|
47
47
|
end
|
48
48
|
else
|
49
49
|
if field.dependent
|
@@ -68,7 +68,8 @@ module Zippo
|
|
68
68
|
hook.call(klass)
|
69
69
|
end if @hooks
|
70
70
|
end
|
71
|
-
|
71
|
+
|
72
|
+
def after_structure_definition(&block)
|
72
73
|
@hooks ||= []
|
73
74
|
@hooks << block
|
74
75
|
end
|
@@ -81,6 +82,7 @@ module Zippo
|
|
81
82
|
end
|
82
83
|
self
|
83
84
|
end
|
85
|
+
|
84
86
|
def size
|
85
87
|
self.class.structure.fields.map do |field|
|
86
88
|
if field.dependent
|
@@ -88,10 +90,10 @@ module Zippo
|
|
88
90
|
else
|
89
91
|
field.width
|
90
92
|
end
|
91
|
-
end.
|
93
|
+
end.reduce(&:+)
|
92
94
|
end
|
93
95
|
|
94
|
-
def convert_to
|
96
|
+
def convert_to(other)
|
95
97
|
other.default.tap do |obj|
|
96
98
|
self.class.common_fields_with(other).each do |field|
|
97
99
|
obj.instance_variable_set "@#{field}", send(field)
|
@@ -9,8 +9,8 @@ module Zippo
|
|
9
9
|
@io = io
|
10
10
|
end
|
11
11
|
|
12
|
-
def pack
|
13
|
-
@io << self.class.structure.fields.map {|f| obj.send f.name}.pack(self.class.structure.fields.map(&:pack).join(""))
|
12
|
+
def pack(obj)
|
13
|
+
@io << self.class.structure.fields.map { |f| obj.send f.name }.pack(self.class.structure.fields.map(&:pack).join(""))
|
14
14
|
end
|
15
15
|
end
|
16
16
|
end
|
@@ -8,7 +8,7 @@ module Zippo::BinaryStructure
|
|
8
8
|
# Defines a method on the specified class that sets a bunch of fields at once.
|
9
9
|
def define_helper(klass, meth, fields)
|
10
10
|
buf = []
|
11
|
-
buf << "def #{meth}(#{0.upto(fields.size-1).map{|x|"a#{x}"}.join(',')})"
|
11
|
+
buf << "def #{meth}(#{0.upto(fields.size - 1).map { |x|"a#{x}" }.join(',')})"
|
12
12
|
fields.each_with_index do |field, i|
|
13
13
|
buf << "@#{field} = a#{i}"
|
14
14
|
end
|
@@ -17,7 +17,7 @@ module Zippo::BinaryStructure
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def fields_as_args(fields)
|
20
|
-
fields.map {|f| "@#{f}"}.join(", ")
|
20
|
+
fields.map { |f| "@#{f}" }.join(", ")
|
21
21
|
end
|
22
22
|
|
23
23
|
def call_helper(receiver, meth, fields)
|
@@ -28,8 +28,8 @@ module Zippo::BinaryStructure
|
|
28
28
|
buf = []
|
29
29
|
buf << "def defaults"
|
30
30
|
klass.structure.fields.each do |field|
|
31
|
-
buf << %
|
32
|
-
buf << %
|
31
|
+
buf << %(@#{field.name} = #{field.options[:default].inspect}) if field.options[:default]
|
32
|
+
buf << %(@#{field.name} = #{field.options[:signature].inspect}) if field.options[:signature]
|
33
33
|
end
|
34
34
|
buf << "self"
|
35
35
|
buf << "end"
|
@@ -39,8 +39,8 @@ module Zippo::BinaryStructure
|
|
39
39
|
# XXX - should write a spec for the "multiple helpers"
|
40
40
|
# implementation, none of the current binary structures would make
|
41
41
|
# use of it, as they all have a bunch of fixed fields,
|
42
|
-
# then the variable fields at the end. a test should
|
43
|
-
#def self.define_unpack_method
|
42
|
+
# then the variable fields at the end. a test should
|
43
|
+
# def self.define_unpack_method
|
44
44
|
def define_unpack_method_for(klass)
|
45
45
|
buf = "def unpack\n"
|
46
46
|
buf << "obj = self.class.structure.owner_class.new\n"
|
@@ -53,7 +53,7 @@ module Zippo::BinaryStructure
|
|
53
53
|
if field.options[:size]
|
54
54
|
# unpack fixed group
|
55
55
|
unless field_buf.empty?
|
56
|
-
s = field_buf.map(&:width).
|
56
|
+
s = field_buf.map(&:width).reduce(&:+)
|
57
57
|
buf << %{arr = @io.read(#{s}).unpack("#{field_buf.map(&:pack).join('')}")\n}
|
58
58
|
helper_name = "binary_structure_unpack_helper_#{helper_num += 1}"
|
59
59
|
define_helper(klass.structure.owner_class, helper_name, field_buf.map(&:name))
|
@@ -104,9 +104,7 @@ module Zippo::BinaryStructure
|
|
104
104
|
"""
|
105
105
|
end
|
106
106
|
|
107
|
-
def define_pack_method_for
|
108
|
-
buf = []
|
109
|
-
|
107
|
+
def define_pack_method_for(klass)
|
110
108
|
fields = klass.structure.fields.map(&:name)
|
111
109
|
packing_string = klass.structure.fields.map(&:pack).join('')
|
112
110
|
|
@@ -137,7 +135,7 @@ module Zippo::BinaryStructure
|
|
137
135
|
end
|
138
136
|
|
139
137
|
module InstanceMethods
|
140
|
-
def convert_to
|
138
|
+
def convert_to(other)
|
141
139
|
method = :"convert_to_#{other.object_id}"
|
142
140
|
::Zippo::BinaryStructure::CodeGen.define_converter_for(self.class, method, other) unless respond_to? method
|
143
141
|
send method
|
@@ -8,13 +8,15 @@ module Zippo
|
|
8
8
|
def initialize(owner_class, &block)
|
9
9
|
@fields = []
|
10
10
|
@owner_class = owner_class
|
11
|
-
instance_eval
|
11
|
+
instance_eval(&block)
|
12
12
|
end
|
13
|
-
|
13
|
+
|
14
|
+
def field(name, pack, options = {})
|
14
15
|
@fields << StructureMember.new(name, pack, options)
|
15
16
|
end
|
16
|
-
|
17
|
-
|
17
|
+
|
18
|
+
def dependent?(field_name)
|
19
|
+
fields.find do |field|
|
18
20
|
field.options[:size] == field_name
|
19
21
|
end
|
20
22
|
end
|
data/lib/zippo/cd_file_header.rb
CHANGED
@@ -8,29 +8,29 @@ module Zippo
|
|
8
8
|
binary_structure do
|
9
9
|
# @!macro [attach] bs.field
|
10
10
|
# @!attribute [rw] $1
|
11
|
-
field :signature, 'L', :
|
12
|
-
field :version_made_by, 'S', :
|
13
|
-
field :version_extractable_by, 'S', :
|
14
|
-
field :bit_flags, 'S', :
|
11
|
+
field :signature, 'L', signature: SIGNATURE
|
12
|
+
field :version_made_by, 'S', default: 0
|
13
|
+
field :version_extractable_by, 'S', default: 20
|
14
|
+
field :bit_flags, 'S', default: 0
|
15
15
|
field :compression_method, 'S'
|
16
|
-
field :last_modified_time, 'S', :
|
17
|
-
field :last_modified_date, 'S', :
|
16
|
+
field :last_modified_time, 'S', default: 0
|
17
|
+
field :last_modified_date, 'S', default: 0
|
18
18
|
field :crc32, 'L'
|
19
19
|
field :compressed_size, 'L'
|
20
20
|
field :uncompressed_size, 'L'
|
21
21
|
# set when name is set
|
22
22
|
field :file_name_length, 'S'
|
23
23
|
# set when extra_field is set
|
24
|
-
field :extra_field_length, 'S', :
|
24
|
+
field :extra_field_length, 'S', default: 0
|
25
25
|
# set when file comment is set
|
26
|
-
field :file_comment_length, 'S', :
|
27
|
-
field :disk_number, 'S', :
|
28
|
-
field :internal_file_attributes, 'S', :
|
29
|
-
field :external_file_attributes, 'L', :
|
26
|
+
field :file_comment_length, 'S', default: 0
|
27
|
+
field :disk_number, 'S', default: 0
|
28
|
+
field :internal_file_attributes, 'S', default: 0
|
29
|
+
field :external_file_attributes, 'L', default: 0
|
30
30
|
field :local_file_header_offset, 'L'
|
31
|
-
field :name, 'a*', :
|
32
|
-
field :extra_field, 'a*', :
|
33
|
-
field :comment, 'a*', :
|
31
|
+
field :name, 'a*', size: :file_name_length
|
32
|
+
field :extra_field, 'a*', size: :extra_field_length, default: ''
|
33
|
+
field :comment, 'a*', size: :file_comment_length, default: ''
|
34
34
|
end
|
35
35
|
end
|
36
36
|
end
|
@@ -11,13 +11,14 @@ module Zippo
|
|
11
11
|
@offset = offset
|
12
12
|
@end = @offset + @size
|
13
13
|
end
|
14
|
+
|
14
15
|
def unpack
|
15
16
|
[].tap do |entries|
|
16
17
|
@io.seek @offset
|
17
|
-
while @io.pos < @end && entry = CdFileHeader::Unpacker.new(@io).unpack
|
18
|
+
while @io.pos < @end && (entry = CdFileHeader::Unpacker.new(@io).unpack)
|
18
19
|
entries << entry
|
19
20
|
end
|
20
21
|
end
|
21
22
|
end
|
22
|
-
|
23
|
+
end
|
23
24
|
end
|
@@ -25,19 +25,20 @@ module Zippo
|
|
25
25
|
|
26
26
|
scan_from = @io.size - EndCdRecord::MAX_COMMENT_LENGTH
|
27
27
|
scan_from = 0 if scan_from < 0
|
28
|
-
scan_from + (read_from(scan_from).rindex(EndCdRecord::PACKED_SIGNATURE) or
|
28
|
+
scan_from + (read_from(scan_from).rindex(EndCdRecord::PACKED_SIGNATURE) or fail "End of Central Directory Record not found")
|
29
29
|
end
|
30
30
|
|
31
31
|
private
|
32
|
+
|
32
33
|
# reads size from the specified offset
|
33
34
|
# if offset is negative, will offset from EOF
|
34
|
-
def read
|
35
|
+
def read(size, offset)
|
35
36
|
@io.seek offset, (offset < 0 ? IO::SEEK_END : IO::SEEK_SET)
|
36
37
|
@io.read size
|
37
38
|
end
|
38
39
|
|
39
40
|
# reads from the specified offset until EOF
|
40
|
-
def read_from
|
41
|
+
def read_from(offset)
|
41
42
|
read nil, offset
|
42
43
|
end
|
43
44
|
end
|
data/lib/zippo/end_cd_record.rb
CHANGED
@@ -5,17 +5,17 @@ module Zippo
|
|
5
5
|
class EndCdRecord
|
6
6
|
SIGNATURE = 0x06054b50
|
7
7
|
PACKED_SIGNATURE = [SIGNATURE].pack('L')
|
8
|
-
MAX_COMMENT_LENGTH = 1<<16
|
8
|
+
MAX_COMMENT_LENGTH = 1 << 16
|
9
9
|
binary_structure do
|
10
|
-
field :signature, 'L', :
|
11
|
-
field :disk, 'S', :
|
12
|
-
field :cd_disk, 'S', :
|
10
|
+
field :signature, 'L', signature: SIGNATURE
|
11
|
+
field :disk, 'S', default: 0
|
12
|
+
field :cd_disk, 'S', default: 0
|
13
13
|
field :records, 'S'
|
14
14
|
field :total_records, 'S'
|
15
15
|
field :cd_size, 'L'
|
16
16
|
field :cd_offset, 'L'
|
17
|
-
field :comment_length, 'S', :
|
18
|
-
field :comment, 'a*', :
|
17
|
+
field :comment_length, 'S', default: 0
|
18
|
+
field :comment, 'a*', default: "", size: :comment_length
|
19
19
|
end
|
20
20
|
end
|
21
21
|
end
|
data/lib/zippo/filter/base.rb
CHANGED
@@ -7,10 +7,11 @@ module Zippo
|
|
7
7
|
BLOCK_SIZE = 131072
|
8
8
|
module ClassMethods
|
9
9
|
def filters
|
10
|
-
@filters_hash ||= Hash[@filters.map{|u| [u::METHOD, u]}]
|
10
|
+
@filters_hash ||= Hash[@filters.map { |u| [u::METHOD, u] }]
|
11
11
|
end
|
12
|
+
|
12
13
|
def for(method)
|
13
|
-
filters[method] or
|
14
|
+
filters[method] or fail "unknown compression method #{method}"
|
14
15
|
end
|
15
16
|
|
16
17
|
def inherited(klass)
|
@@ -21,22 +21,22 @@ module Zippo::Filter
|
|
21
21
|
@io = io
|
22
22
|
end
|
23
23
|
|
24
|
-
def read
|
24
|
+
def read(count = nil, buf = nil)
|
25
25
|
@io.read count, buf
|
26
26
|
end
|
27
27
|
|
28
|
-
def compress_to
|
28
|
+
def compress_to(io)
|
29
29
|
data_size = 0
|
30
30
|
compressed_size = 0
|
31
31
|
crc32 = 0
|
32
32
|
buf = ""
|
33
|
-
while
|
33
|
+
while read BLOCK_SIZE, buf
|
34
34
|
data_size += buf.bytesize
|
35
35
|
compressed_size += io.write filter(buf)
|
36
36
|
crc32 = Zlib.crc32(buf, crc32)
|
37
37
|
end
|
38
38
|
compressed_size += io.write tail_filter
|
39
|
-
|
39
|
+
[compressed_size, data_size, crc32]
|
40
40
|
end
|
41
41
|
end
|
42
42
|
end
|