Ascii85 0.9.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data.tar.gz.sig CHANGED
Binary file
data/History.txt CHANGED
@@ -1,3 +1,10 @@
1
+ === 1.0.0 / 2009-12-25
2
+
3
+ * 2 major enhancements
4
+
5
+ * Ruby 1.9 compatibility
6
+ * Added command-line en- and decoder
7
+
1
8
  === 0.9.0 / 2009-02-17
2
9
 
3
10
  * 1 major enhancement
data/Manifest.txt CHANGED
@@ -2,5 +2,6 @@ History.txt
2
2
  Manifest.txt
3
3
  README.txt
4
4
  Rakefile
5
+ bin/ascii85
5
6
  lib/ascii85.rb
6
7
  spec/ascii85_spec.rb
data/README.txt CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  * http://ascii85.rubyforge.org
4
4
 
5
+
5
6
  == DESCRIPTION:
6
7
 
7
8
  Ascii85 is a simple gem that provides methods for encoding/decoding Adobe's
@@ -25,13 +26,29 @@ http://en.wikipedia.org/wiki/Ascii85 for more information about the format.
25
26
  In addition, Ascii85::encode can take a second parameter that specifies the
26
27
  length of the returned lines. The default is 80; use +false+ for unlimited.
27
28
 
28
- Ascii85::decode expects the input to be enclosed in <~ and ~>. It ignores
29
- everything outside of these.
29
+ Ascii85::decode expects the input to be enclosed in <~ and ~> it
30
+ ignores everything outside of these. The output of Ascii85::decode
31
+ will have the ASCII-8BIT encoding, so in Ruby 1.9 you may have to use
32
+ <tt>String#force_encoding</tt> to correct the encoding.
33
+
34
+
35
+ == Command-line utility
36
+
37
+ This gem includes +ascii85+, a command-line utility modeled after +base64+ from
38
+ the GNU coreutils. It can be used to encode/decode Ascii85 directly from the
39
+ command-line:
40
+
41
+ Usage: ascii85 [OPTIONS] [FILE]
42
+ Encodes or decodes FILE or STDIN using Ascii85 and write to STDOUT.
43
+ -w, --wrap COLUMN Wrap lines at COLUMN. Default is 80, use 0 for no wrapping
44
+ -d, --decode Decode the input
45
+ -h, --help Display this help and exit
46
+ --version Output version information
30
47
 
31
48
 
32
49
  == INSTALL:
33
50
 
34
- * sudo gem install ascii85
51
+ * sudo gem install Ascii85
35
52
 
36
53
 
37
54
  == LICENSE:
@@ -40,20 +57,20 @@ everything outside of these.
40
57
 
41
58
  Copyright (c) 2009 Johannes Holzfuß
42
59
 
43
- Permission is hereby granted, free of charge, to any person obtaining a
44
- copy of this software and associated documentation files (the "Software"),
45
- to deal in the Software without restriction, including without limitation the
46
- rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
47
- sell copies of the Software, and to permit persons to whom the Software is
48
- furnished to do so, subject to the following conditions:
60
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
61
+ this software and associated documentation files (the "Software"), to deal in
62
+ the Software without restriction, including without limitation the rights to
63
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
64
+ of the Software, and to permit persons to whom the Software is furnished to do
65
+ so, subject to the following conditions:
49
66
 
50
- The above copyright notice and this permission notice shall be included in
51
- all copies or substantial portions of the Software.
67
+ The above copyright notice and this permission notice shall be included in all
68
+ copies or substantial portions of the Software.
52
69
 
53
70
  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
54
71
  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
55
72
  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
56
73
  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
57
74
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
58
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
59
- THE SOFTWARE.
75
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
76
+ SOFTWARE.
data/Rakefile CHANGED
@@ -1,43 +1,23 @@
1
+ # encoding: utf-8
1
2
 
2
3
  require 'rubygems'
3
-
4
4
  require 'hoe'
5
- require 'rake'
6
- require 'rake/clean'
7
- require 'rake/rdoctask'
8
- require 'spec/rake/spectask'
9
-
10
- require 'lib/ascii85.rb'
11
-
12
-
13
- # rspec
14
-
15
- desc "Run specs"
16
- Spec::Rake::SpecTask.new do |t|
17
- t.spec_opts = ["--color"]
18
- end
19
-
20
- desc "Show specdoc"
21
- Spec::Rake::SpecTask.new('specdoc') do |t|
22
- t.spec_opts = ["--color", "--format=specdoc"]
23
- end
24
5
 
6
+ Hoe.spec 'Ascii85' do
25
7
 
26
- # Hoe
8
+ developer \
9
+ "Johannes Holzfuß",
10
+ "Drangon@gmx.de"
27
11
 
28
- Hoe.new('Ascii85', Ascii85::VERSION) do |p|
29
- p.author = "Johannes Holzfuß"
30
- p.email = "Drangon@gmx.de"
31
- p.summary = "Ascii85 encoder/decoder"
12
+ summary
13
+ "Ascii85 encoder/decoder"
32
14
 
33
- p.description = "Ascii85 provides methods to encode/decode Adobe's binary-to-text encoding of the same name."
15
+ description
16
+ "Ascii85 provides methods to encode/decode Adobe's binary-to-text encoding"
17
+ "of the same name."
34
18
 
35
- p.remote_rdoc_dir = ''
19
+ self.url =
20
+ ["http://ascii85.rubyforge.org", "http://github.com/drangon/ascii85gem"]
36
21
 
37
- p.testlib = "spec"
38
- p.test_globs = "spec/ascii85_spec.rb"
22
+ self.testlib = "spec"
39
23
  end
40
-
41
-
42
- # default task is spec
43
- task :default => :spec
data/bin/ascii85 ADDED
@@ -0,0 +1,82 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: utf-8
3
+
4
+ #
5
+ # A simple command-line tool to de- and encode Ascii85, modeled after `base64`
6
+ # from the GNU Coreutils.
7
+ #
8
+
9
+
10
+ require "optparse"
11
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'ascii85')
12
+
13
+ @options = {
14
+ :wrap => 80,
15
+ :decode => false
16
+ }
17
+
18
+ ARGV.options do |opts|
19
+ opts.banner = "Usage: #{File.basename($PROGRAM_NAME)} [OPTIONS] [FILE]\n" +
20
+ "Encodes or decodes FILE or STDIN using Ascii85 and write to STDOUT."
21
+
22
+
23
+ opts.on( "-w", "--wrap COLUMN", Integer,
24
+ "Wrap lines at COLUMN. Default is 80, use 0 for no wrapping") do |opt|
25
+
26
+ @options[:wrap] = opt.abs
27
+ @options[:wrap] = false if opt.zero?
28
+ end
29
+
30
+ opts.on( "-d", "--decode", "Decode the input") do
31
+ @options[:decode] = true
32
+ end
33
+
34
+ opts.on( "-h", "--help", "Display this help and exit") do
35
+ puts opts
36
+ exit
37
+ end
38
+
39
+ opts.on( "--version", "Output version information") do |opt|
40
+ puts "Ascii85 v#{Ascii85::VERSION},\nwritten by Johannes Holzfuß"
41
+ exit
42
+ end
43
+
44
+ remaining_args = opts.parse!
45
+
46
+ case remaining_args.size
47
+ when 0
48
+ @options[:file] = '-'
49
+ when 1
50
+ @options[:file] = remaining_args.first
51
+ else
52
+ abort "Superfluous operand(s): \"#{remaining_args.join('", "')}\""
53
+ end
54
+
55
+ end
56
+
57
+ if @options[:file] == '-'
58
+ $stdin.binmode
59
+ @input = $stdin.read
60
+ else
61
+ unless File.exists?(@options[:file])
62
+ abort "File not found: \"#{@options[:file]}\""
63
+ end
64
+
65
+ unless File.readable_real?(@options[:file])
66
+ abort "File is not readable: \"#{@options[:file]}\""
67
+ end
68
+
69
+ File.open(@options[:file], 'rb') do |f|
70
+ @input = f.read
71
+ end
72
+ end
73
+
74
+ if @options[:decode]
75
+ begin
76
+ print Ascii85::decode(@input)
77
+ rescue Ascii85::DecodingError => error
78
+ abort "Decoding Error: #{error.message.to_s}"
79
+ end
80
+ else
81
+ print Ascii85::encode(@input, @options[:wrap])
82
+ end
data/lib/ascii85.rb CHANGED
@@ -1,3 +1,6 @@
1
+ # encoding: utf-8
2
+
3
+
1
4
  #
2
5
  # Ascii85 is an implementation of Adobe's binary-to-text encoding of the same
3
6
  # name in pure Ruby.
@@ -12,13 +15,13 @@
12
15
 
13
16
  module Ascii85
14
17
  # The gem version number
15
- VERSION = '0.9.0' # :nodoc:
18
+ VERSION = '1.0.0' # :nodoc:
16
19
 
17
20
  #
18
- # Encodes the given String as Ascii85.
21
+ # Encodes the bytes of the given String as Ascii85.
19
22
  #
20
- # If +wrap_lines+ evaluates to +false+, the output will be returned as a
21
- # single long line. Otherwise #encode formats the output into lines of
23
+ # If +wrap_lines+ evaluates to +false+, the output will be returned as
24
+ # a single long line. Otherwise #encode formats the output into lines of
22
25
  # length +wrap_lines+ (minimum is 2).
23
26
  #
24
27
  # Ascii85::encode("Ruby")
@@ -36,13 +39,21 @@ module Ascii85
36
39
  #
37
40
  def self.encode(str, wrap_lines = 80)
38
41
 
39
- return '' if str.to_s.empty?
42
+ to_encode = str.to_s
43
+ return '' if to_encode.empty?
44
+
45
+ # Deal with multi-byte encodings
46
+ if to_encode.methods.include?(:bytesize)
47
+ input_size = to_encode.bytesize
48
+ else
49
+ input_size = to_encode.size
50
+ end
40
51
 
41
52
  # Compute number of \0s to pad the message with (0..3)
42
- padding_length = (-str.to_s.length) % 4
53
+ padding_length = (-input_size) % 4
43
54
 
44
55
  # Extract big-endian integers
45
- tuples = (str.to_s + ("\0" * padding_length)).unpack('N*')
56
+ tuples = (to_encode + ("\0" * padding_length)).unpack('N*')
46
57
 
47
58
  # Encode
48
59
  tuples.map! do |tuple|
@@ -51,7 +62,7 @@ module Ascii85
51
62
  else
52
63
  tmp = ""
53
64
  5.times do
54
- tmp += ((tuple % 85) + 33).chr
65
+ tmp << ((tuple % 85) + 33).chr
55
66
  tuple /= 85
56
67
  end
57
68
  tmp.reverse
@@ -66,12 +77,9 @@ module Ascii85
66
77
  # Cut off the padding
67
78
  tuples[-1] = tuples[-1][0..(4 - padding_length)]
68
79
 
69
- # Add start-marker and join into a String
70
- result = '<~' + tuples.join
71
-
72
- # If we don't need to wrap the lines to a certain length, add ~> and return
80
+ # If we don't need to wrap the lines, add delimiters and return
73
81
  if (!wrap_lines)
74
- return result + '~>'
82
+ return '<~' + tuples.join + '~>'
75
83
  end
76
84
 
77
85
  # Otherwise we wrap the lines
@@ -79,15 +87,17 @@ module Ascii85
79
87
  line_length = [2, wrap_lines.to_i].max
80
88
 
81
89
  wrapped = []
82
- 0.step(result.length, line_length) do |index|
83
- wrapped << result.slice(index, line_length)
90
+ to_wrap = '<~' + tuples.join
91
+
92
+ 0.step(to_wrap.length, line_length) do |index|
93
+ wrapped << to_wrap.slice(index, line_length)
84
94
  end
85
95
 
86
- # Add end-marker -- on a new line if necessary
96
+ # Add end-marker on a new line if necessary
87
97
  if (wrapped.last.length + 2) > line_length
88
98
  wrapped << '~>'
89
99
  else
90
- wrapped[-1] += '~>'
100
+ wrapped[-1] << '~>'
91
101
  end
92
102
 
93
103
  return wrapped.join("\n")
@@ -96,8 +106,9 @@ module Ascii85
96
106
  #
97
107
  # Searches through +str+ and decodes the _first_ Ascii85-String found.
98
108
  #
99
- # #decode expects an Ascii85-encoded String enclosed in <~ and ~>. It will
100
- # ignore all characters outside these markers.
109
+ # #decode expects an Ascii85-encoded String enclosed in <~ and ~> it
110
+ # will ignore all characters outside these markers. The returned strings are
111
+ # always encoded as ASCII-8BIT.
101
112
  #
102
113
  # Ascii85::decode("<~;KZGo~>")
103
114
  # => "Ruby"
@@ -113,15 +124,32 @@ module Ascii85
113
124
  #
114
125
  def self.decode(str)
115
126
 
116
- # Find the Ascii85 encoded data between <~ and ~>
117
- input = str.to_s.match(/<~.*?~>/mn)
127
+ input = str.to_s
118
128
 
119
- return '' if input.nil?
129
+ # Try to compile the regular expression for finding the input between
130
+ # the <~ and ~> delimiters. In order to work properly with different
131
+ # input encodings, the RegExp itself is re-encoded to the input encoding
132
+ # if possible. Thanks to Myrddin Emrys for suggesting this approach
133
+ # (http://is.gd/5x18O)
134
+ begin
135
+ regex = "<~(.*?)?~>"
136
+
137
+ if regex.methods.include?(:encode)
138
+ regex = regex.encode(input.encoding)
139
+ end
140
+ regex = Regexp.compile(regex, Regexp::MULTILINE)
141
+
142
+ # Find the actual data to be decoded
143
+ input = input.match(regex)
120
144
 
121
- # Remove the delimiters
122
- input = input.to_s[2..-3]
145
+ rescue EncodingError
146
+ raise ArgumentError, "Incompatible input encoding: #{str.encoding.inspect}"
147
+ end
148
+
149
+ return '' if input.nil?
123
150
 
124
- return '' if input.empty?
151
+ # Get the matched data as String
152
+ input = input.captures.first
125
153
 
126
154
  # Decode
127
155
  result = []
@@ -182,9 +210,9 @@ module Ascii85
182
210
  count -= 1
183
211
  word += 85**(4 - count)
184
212
 
185
- result += ((word >> 24) & 255).chr if count >= 1
186
- result += ((word >> 16) & 255).chr if count >= 2
187
- result += ((word >> 8) & 255).chr if count == 3
213
+ result << ((word >> 24) & 255).chr if count >= 1
214
+ result << ((word >> 16) & 255).chr if count >= 2
215
+ result << ((word >> 8) & 255).chr if count == 3
188
216
  end
189
217
 
190
218
  return result
data/spec/ascii85_spec.rb CHANGED
@@ -6,6 +6,10 @@ require 'ascii85'
6
6
 
7
7
  describe Ascii85 do
8
8
 
9
+ before( :all ) do
10
+ @string_has_encoding = "String".methods.include?(:encoding)
11
+ end
12
+
9
13
  TEST_CASES = {
10
14
 
11
15
  "" => "",
@@ -61,6 +65,15 @@ describe Ascii85 do
61
65
  end
62
66
  end
63
67
 
68
+ it "[Ruby 1.9] should encode Strings in different encodings correctly" do
69
+ if @string_has_encoding
70
+ input_EUC_JP = 'どうもありがとうミスターロボット'.encode('EUC-JP')
71
+ input_Ascii85 = input_EUC_JP.force_encoding('ASCII-8BIT')
72
+
73
+ Ascii85::encode(input_EUC_JP).should == Ascii85::encode(input_Ascii85)
74
+ end
75
+ end
76
+
64
77
  it "should produce output lines no longer than specified" do
65
78
  test_str = '0123456789' * 30
66
79
 
@@ -105,13 +118,40 @@ describe Ascii85 do
105
118
 
106
119
  it "should decode all specified test-cases correctly" do
107
120
  TEST_CASES.each_pair do |decoded, input|
108
- Ascii85::decode(input).should == decoded
121
+ if @string_has_encoding
122
+ Ascii85::decode(input).should == decoded.dup.force_encoding('ASCII-8BIT')
123
+ else
124
+ Ascii85::decode(input).should == decoded
125
+ end
126
+ end
127
+ end
128
+
129
+ it "[Ruby 1.9] should accept valid input in encodings other than the default" do
130
+ if @string_has_encoding
131
+ input = "Ragnarök τέχνη русский язык I ♥ Ruby"
132
+ input_ascii85 = Ascii85::encode(input)
133
+
134
+ # Try to encode input_ascii85 in all possible encodings and see if we
135
+ # do the right thing in #decode.
136
+ Encoding.list.each do |encoding|
137
+ next if encoding.dummy?
138
+
139
+ to_test = input_ascii85.encode(encoding)
140
+
141
+ lambda {
142
+ Ascii85::decode(to_test).force_encoding('UTF-8').should == input
143
+ }.should_not raise_error
144
+ end
145
+
109
146
  end
110
147
  end
111
148
 
112
- it "should ignore everything before/after the delimiter-pairs" do
149
+ it "should only process data within delimiters" do
113
150
  Ascii85::decode("Doesn't contain delimiters").should == ''
151
+ Ascii85::decode("<~~>").should == ''
114
152
  Ascii85::decode("FooBar<~z~>BazQux").should == ("\0" * 4)
153
+ Ascii85::decode("<~;KZGo~><~z~>").should == "Ruby"
154
+ Ascii85::decode("foo~>bar<~baz").should == ''
115
155
  end
116
156
 
117
157
  it "should ignore whitespace" do
@@ -119,6 +159,12 @@ describe Ascii85 do
119
159
  decoded.should == 'Antidisestablishmentarianism'
120
160
  end
121
161
 
162
+ it "[Ruby 1.9] should return ASCII-8BIT encoded strings" do
163
+ if @string_has_encoding
164
+ Ascii85::decode("<~;KZGo~>").encoding.name.should == "ASCII-8BIT"
165
+ end
166
+ end
167
+
122
168
  describe "Error conditions" do
123
169
 
124
170
  it "should raise DecodingError if it encounters a word >= 2**32" do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: Ascii85
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - "Johannes Holzfu\xC3\x9F"
@@ -29,7 +29,7 @@ cert_chain:
29
29
  5FGhYN16QZS8VKLApBtxxP9XmwFASMyJLNizTN2q6hCCy/MjoTzHWzodPaWm0Q==
30
30
  -----END CERTIFICATE-----
31
31
 
32
- date: 2009-02-17 00:00:00 +01:00
32
+ date: 2009-12-25 00:00:00 +01:00
33
33
  default_executable:
34
34
  dependencies:
35
35
  - !ruby/object:Gem::Dependency
@@ -40,12 +40,18 @@ dependencies:
40
40
  requirements:
41
41
  - - ">="
42
42
  - !ruby/object:Gem::Version
43
- version: 1.8.3
43
+ version: 2.4.0
44
44
  version:
45
- description: Ascii85 provides methods to encode/decode Adobe's binary-to-text encoding of the same name.
46
- email: Drangon@gmx.de
47
- executables: []
48
-
45
+ description: |-
46
+ Ascii85 is a simple gem that provides methods for encoding/decoding Adobe's
47
+ binary-to-text encoding of the same name.
48
+
49
+ See http://www.adobe.com/products/postscript/pdfs/PLRM.pdf page 131 and
50
+ http://en.wikipedia.org/wiki/Ascii85 for more information about the format.
51
+ email:
52
+ - Drangon@gmx.de
53
+ executables:
54
+ - ascii85
49
55
  extensions: []
50
56
 
51
57
  extra_rdoc_files:
@@ -57,10 +63,13 @@ files:
57
63
  - Manifest.txt
58
64
  - README.txt
59
65
  - Rakefile
66
+ - bin/ascii85
60
67
  - lib/ascii85.rb
61
68
  - spec/ascii85_spec.rb
62
69
  has_rdoc: true
63
70
  homepage: http://ascii85.rubyforge.org
71
+ licenses: []
72
+
64
73
  post_install_message:
65
74
  rdoc_options:
66
75
  - --main
@@ -82,9 +91,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
82
91
  requirements: []
83
92
 
84
93
  rubyforge_project: ascii85
85
- rubygems_version: 1.3.1
94
+ rubygems_version: 1.3.5
86
95
  signing_key:
87
- specification_version: 2
88
- summary: Ascii85 encoder/decoder
89
- test_files:
90
- - spec/ascii85_spec.rb
96
+ specification_version: 3
97
+ summary: Ascii85 is a simple gem that provides methods for encoding/decoding Adobe's binary-to-text encoding of the same name
98
+ test_files: []
99
+
metadata.gz.sig CHANGED
Binary file