Module: Bencoding::Parser

Extended by:
Parser
Included in:
Parser
Defined in:
lib/bencoding/parser.rb

Constant Summary collapse

DICTIONARY_TOKEN =

d # :nodoc:

100
LIST_TOKEN =

l # :nodoc:

108
INTEGER_TOKEN =

i # :nodoc:

105
TERMINATOR_TOKEN =

e # :nodoc:

101
SEPERATOR_TOKEN =

: # :nodoc:

58
ZERO_TOKEN =

0 # :nodoc:

48
NINE_TOKEN =

9 # :nodoc:

57
MINUS_TOKEN =
  • # :nodoc:

45

Instance Method Summary collapse

Instance Method Details

#any_io(io) ⇒ Object

Raises:



22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/bencoding/parser.rb', line 22

def any_io(io)
  close_io = false
  if io.is_a? String
    if io =~ %r{^(http(s?)|file)://}
      io = open(io)
      close_io = true
    elsif File.exist?(io)
      io = File.open(io)
      close_io = true
    else
      io = StringIO.new(io)
    end
  end
  
  raise InvalidInput unless io.respond_to?(:getc)
  raise InvalidInput unless io.respond_to?(:read)
  raise InvalidInput unless io.respond_to?(:close) or not close_io
  
  return_value = yield(io)
  
  io.close if close_io
  return return_value
end

#load(io) ⇒ Object



16
17
18
19
20
# File 'lib/bencoding/parser.rb', line 16

def load(io)
  any_io(io) do |io|
    parse_anytype(io)
  end
end

#parse_anytype(io, typechar = nil) ⇒ Object

:nodoc:



46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/bencoding/parser.rb', line 46

def parse_anytype(io, typechar=nil) # :nodoc:
  typechar ||= io.getc
  case typechar
  when DICTIONARY_TOKEN then parse_dictionary(io)
  when LIST_TOKEN       then parse_list(io)
  when INTEGER_TOKEN    then parse_integer(io)
  when (ZERO_TOKEN..NINE_TOKEN)
    parse_string(io, typechar)
  else
    raise ParseError
  end
end

#parse_dictionary(io) ⇒ Object

:nodoc:



59
60
61
62
63
64
65
66
67
68
# File 'lib/bencoding/parser.rb', line 59

def parse_dictionary(io) # :nodoc:
  dictionary = ::Hash.new
  until (c = io.getc) == TERMINATOR_TOKEN
    raise ParseError if c.nil?
    key = parse_string(io, c)
    val = parse_anytype(io)
    dictionary[key] = val
  end
  dictionary
end

#parse_integer(io, terminator = TERMINATOR_TOKEN, first_char = nil) ⇒ Object

:nodoc:



80
81
82
83
84
85
86
87
88
89
# File 'lib/bencoding/parser.rb', line 80

def parse_integer(io, terminator=TERMINATOR_TOKEN, first_char=nil) # :nodoc:
  integer_string = ""
  integer_string << first_char unless first_char.nil?
  until (c = io.getc) == terminator
    raise ParseError if c.nil? 
    raise ParseError unless (ZERO_TOKEN..NINE_TOKEN).member?(c) or MINUS_TOKEN == c
    integer_string << c
  end
  integer_string.to_i
end

#parse_list(io) ⇒ Object

:nodoc:



70
71
72
73
74
75
76
77
78
# File 'lib/bencoding/parser.rb', line 70

def parse_list(io) # :nodoc:
  list = ::Array.new
  until (c = io.getc) == TERMINATOR_TOKEN
    raise ParseError if c.nil?
    val = parse_anytype(io, c)
    list << val
  end
  list
end

#parse_string(io, first_char) ⇒ Object

:nodoc:

Raises:



91
92
93
94
95
96
97
# File 'lib/bencoding/parser.rb', line 91

def parse_string(io, first_char) # :nodoc:
  length = parse_integer(io, SEPERATOR_TOKEN, first_char)
  raise ParseError if length < 0
  string = io.read(length)
  raise ParseError if length != string.length
  string
end