zippo 0.2.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![Build Status](https://travis-ci.org/JonathonMA/zippo.svg?branch=master)](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
|