simonmenke-bencoding 0.0.2 → 0.0.3

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/History.txt CHANGED
@@ -1,3 +1,12 @@
1
+ == 0.0.3 3008-09-13
2
+
3
+ * 5 major enhancement:
4
+ * Allow loading URIs and file paths
5
+ * automatic detection of input type
6
+ * no more ungetc (I didn't like it)
7
+ * better error handeling
8
+ * more tests
9
+
1
10
  == 0.0.2 2008-09-01
2
11
 
3
12
  * 3 major enhancement:
data/README.txt CHANGED
@@ -13,6 +13,11 @@ this gem loads and dumps bencoded data
13
13
 
14
14
  == SYNOPSIS:
15
15
 
16
+ Bencoding.load(path)
17
+ Bencoding.load(url)
18
+ Bencoding.load(string)
19
+ Bencoding.load(io)
20
+
16
21
  File.open("path/to/file.bencoding", "r") do |f|
17
22
  data = Bencoding.load(f)
18
23
  end
data/lib/bencoding.rb CHANGED
@@ -1,12 +1,16 @@
1
1
  $:.unshift(File.dirname(__FILE__)) unless
2
2
  $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
3
3
 
4
- require "stringio"
4
+ require 'stringio'
5
+ require 'open-uri'
5
6
 
6
7
  module Bencoding
7
- def self.load(io)
8
+ def self.load!(io)
8
9
  Parser.load(io)
9
10
  end
11
+ def self.load(io)
12
+ return load!(io) rescue nil
13
+ end
10
14
  def self.dump(object)
11
15
  object.to_bencoding
12
16
  end
@@ -1,5 +1,6 @@
1
1
  module Bencoding
2
- class ParseError < Exception ; end
2
+ class ParseError < Exception ; end
3
+ class InvalidInput < Exception ; end
3
4
 
4
5
  module Parser
5
6
 
@@ -8,12 +9,38 @@ module Bencoding
8
9
  INTEGER_TOKEN = 105 # i # :nodoc:
9
10
  TERMINATOR_TOKEN = 101 # e # :nodoc:
10
11
  SEPERATOR_TOKEN = 58 # : # :nodoc:
11
- ZERO_TOKEN = 48 # : # :nodoc:
12
- NINE_TOKEN = 57 # : # :nodoc:
12
+ ZERO_TOKEN = 48 # 0 # :nodoc:
13
+ NINE_TOKEN = 57 # 9 # :nodoc:
14
+ MINUS_TOKEN = 45 # - # :nodoc:
13
15
 
14
16
  def load(io)
15
- io = StringIO.new(io) if io.is_a? String
16
- parse_anytype(io)
17
+ any_io(io) do |io|
18
+ parse_anytype(io)
19
+ end
20
+ end
21
+
22
+ def any_io(io)
23
+ close_io = false
24
+ if io.is_a? String
25
+ if io =~ %r{^(http(s?)|file)://}
26
+ io = open(io)
27
+ close_io = true
28
+ elsif File.exist?(io)
29
+ io = File.open(io)
30
+ close_io = true
31
+ else
32
+ io = StringIO.new(io)
33
+ end
34
+ end
35
+
36
+ raise InvalidInput unless io.respond_to?(:getc)
37
+ raise InvalidInput unless io.respond_to?(:read)
38
+ raise InvalidInput unless io.respond_to?(:close) or not close_io
39
+
40
+ return_value = yield(io)
41
+
42
+ io.close if close_io
43
+ return return_value
17
44
  end
18
45
 
19
46
  def parse_anytype(io, typechar=nil) # :nodoc:
@@ -23,8 +50,7 @@ module Bencoding
23
50
  when LIST_TOKEN then parse_list(io)
24
51
  when INTEGER_TOKEN then parse_integer(io)
25
52
  when (ZERO_TOKEN..NINE_TOKEN)
26
- io.ungetc typechar
27
- parse_string(io)
53
+ parse_string(io, typechar)
28
54
  else
29
55
  raise ParseError
30
56
  end
@@ -34,8 +60,7 @@ module Bencoding
34
60
  dictionary = ::Hash.new
35
61
  until (c = io.getc) == TERMINATOR_TOKEN
36
62
  raise ParseError if c.nil?
37
- io.ungetc c
38
- key = parse_string(io)
63
+ key = parse_string(io, c)
39
64
  val = parse_anytype(io)
40
65
  dictionary[key] = val
41
66
  end
@@ -52,18 +77,23 @@ module Bencoding
52
77
  list
53
78
  end
54
79
 
55
- def parse_integer(io, terminator=TERMINATOR_TOKEN) # :nodoc:
80
+ def parse_integer(io, terminator=TERMINATOR_TOKEN, first_char=nil) # :nodoc:
56
81
  integer_string = ""
82
+ integer_string << first_char unless first_char.nil?
57
83
  until (c = io.getc) == terminator
58
- raise ParseError if c.nil?
59
- integer_string << c.chr
84
+ raise ParseError if c.nil?
85
+ raise ParseError unless (ZERO_TOKEN..NINE_TOKEN).member?(c) or MINUS_TOKEN == c
86
+ integer_string << c
60
87
  end
61
88
  integer_string.to_i
62
89
  end
63
90
 
64
- def parse_string(io) # :nodoc:
65
- length = parse_integer(io, SEPERATOR_TOKEN)
66
- io.read(length)
91
+ def parse_string(io, first_char) # :nodoc:
92
+ length = parse_integer(io, SEPERATOR_TOKEN, first_char)
93
+ raise ParseError if length < 0
94
+ string = io.read(length)
95
+ raise ParseError if length != string.length
96
+ string
67
97
  end
68
98
 
69
99
  extend self
@@ -2,7 +2,7 @@ module Bencoding
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 0
4
4
  MINOR = 0
5
- TINY = 2
5
+ TINY = 3
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
8
8
  end
@@ -10,6 +10,10 @@ class TestBencoding < Test::Unit::TestCase
10
10
  test_load "i17e", 17
11
11
  end
12
12
 
13
+ def test_load_negative_integer
14
+ test_load "i-17e", -17
15
+ end
16
+
13
17
  def test_load_list
14
18
  test_load "l5:helloi17ee", ["hello", 17]
15
19
  end
@@ -22,10 +26,36 @@ class TestBencoding < Test::Unit::TestCase
22
26
  def test_load_fake
23
27
  str = "d5:key_ai16e5:a_key4:helloe"
24
28
  assert_raise Bencoding::ParseError do
25
- out = Bencoding.load(str)
29
+ out = Bencoding.load!(str)
30
+ end
31
+ end
32
+
33
+ def test_load_partial_integer
34
+ str = "i12"
35
+ assert_raise Bencoding::ParseError do
36
+ out = Bencoding.load!(str)
37
+ end
38
+ end
39
+
40
+ def test_load_partial_integer_in_list
41
+ str = "li12i45ee"
42
+ assert_raise Bencoding::ParseError do
43
+ out = Bencoding.load!(str)
44
+ end
45
+ end
46
+
47
+ def test_load_partial_string
48
+ str = "5:hel"
49
+ assert_raise Bencoding::ParseError do
50
+ out = Bencoding.load!(str)
26
51
  end
27
52
  end
28
53
 
54
+ def test_load_form_uri
55
+ uri = "http://torrents.thepiratebay.org/4385574/Ubuntu_8.10_(Intrepid_Ibex)_Alpha_5.4385574.TPB.torrent"
56
+ assert Bencoding.load!(uri)['announce']=='http://tpb.tracker.thepiratebay.org:80/announce'
57
+ end
58
+
29
59
  def test_dump_string
30
60
  test_dump "hello", "5:hello"
31
61
  end
@@ -34,6 +64,10 @@ class TestBencoding < Test::Unit::TestCase
34
64
  test_dump 25, "i25e"
35
65
  end
36
66
 
67
+ def test_dump_negative_integer
68
+ test_dump -25, "i-25e"
69
+ end
70
+
37
71
  def test_dump_float
38
72
  test_dump 25.4, "i25e"
39
73
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: simonmenke-bencoding
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Simon Menke
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-09-01 00:00:00 -07:00
12
+ date: 2008-09-13 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency