summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoro <o@immerda.ch>2011-06-27 15:05:12 +0200
committero <o@immerda.ch>2011-06-27 15:05:12 +0200
commitebde938e0d391192bd9a6f343ee52d2dc315719c (patch)
tree08ee9122b9f9ba650128f71a626882dfd44d7fcd
parentb92ce2ee90910da67a4e040312f184f65a020282 (diff)
fixed handling of partial sized headers
-rw-r--r--lib/fpg/io/zappable_byte_stream.rb31
-rw-r--r--lib/fpg/parse/packet.rb64
-rw-r--r--spec/zappable_byte_stream_spec.rb19
3 files changed, 65 insertions, 49 deletions
diff --git a/lib/fpg/io/zappable_byte_stream.rb b/lib/fpg/io/zappable_byte_stream.rb
index a80c82a..73ba0b6 100644
--- a/lib/fpg/io/zappable_byte_stream.rb
+++ b/lib/fpg/io/zappable_byte_stream.rb
@@ -1,18 +1,21 @@
module FPG
module Io
class ZappableByteStream
- attr_accessor :io, :zapped
+ attr_accessor :io, :zapped, :pos
def initialize(io)
- self.io = io
- self.zapped = {}
+ @io = io
+ @zapped = {}
+ @pos = io.pos
end
def zap(n=1)
+ @pos -= n
(1..n).each do |i|
self.zapped[io.pos-i] = true
end
end
def getbyte
ret = io.getbyte
+ @pos += 1
skip_to_next_byte
ret
end
@@ -24,28 +27,30 @@ module FPG
ret
end
def rewind
+ @pos = 0
io.rewind
skip_to_next_byte
end
def eof?
io.eof?
end
- def pos=(pos)
- skip = zapped.keys.select{ |p| p < pos }.size
- io.pos= pos+skip
- end
- def pos
- io.pos
+ def pos=(position)
+ @pos = position
+ io.pos= to_internal_pos(position)
end
def seek(n,wh)
raise 'only support relative positioning' unless wh == IO::SEEK_CUR
- n.times do
- io.seek(1,IO::SEEK_CUR)
- skip_to_next_byte
- end
+ self.pos= @pos+n
end
private
+ def to_internal_pos(position)
+ zapped.keys.sort.each do |p|
+ break if p > position
+ position += 1
+ end
+ position
+ end
def skip_to_next_byte
io.readbyte while zapped[io.pos]
end
diff --git a/lib/fpg/parse/packet.rb b/lib/fpg/parse/packet.rb
index d845437..499ecae 100644
--- a/lib/fpg/parse/packet.rb
+++ b/lib/fpg/parse/packet.rb
@@ -5,9 +5,7 @@ module FPG
def parse( stream )
header = stream.getbyte
stream.seek(-1,IO::SEEK_CUR)
- unless packet_header?(header)
- debug_header_search(stream)
- end
+ raise "i expected a packet header but there is none" unless packet_header?(header)
with_tag(packet_number(header)).parse(stream)
end
def packet_number(byte)
@@ -23,49 +21,45 @@ module FPG
def new_packet?(byte)
byte>>6 == 3
end
- def debug_header_search(stream)
- current_pos = stream.pos+1
- stream.seek(-2,IO::SEEK_CUR)
- 4.times do
- if packet_header?(stream.getbyte) then
- raise "i expected a packet header but found none. it could to be off by #{current_pos-stream.pos}"
- end
- end
- raise "i expected a packet header but there is none"
- end
end
def self.included(base)
base.extend PacketParserKlass
end
- attr_accessor :stream, :partial_length, :partial_byte_size
+ attr_accessor :stream, :partial_length
def parse(stream)
- self.stream = stream
- self.byte_size = self.partial_byte_size = packet_size
- if partial_length? then
- self.stream = ZappableByteStream.new(stream)
- start = self.stream.pos
- while partial_length? do
- size = new_packet_size
- self.partial_byte_size = size[:s]
- self.byte_size += size[:s]-size[:h]
- #remove the header packets from the stream => subclasses wont have to worry abouth this
- self.stream.zap(size[:h])
- end
- self.stream.pos= start
- end
+ @stream = stream
+ @byte_size = packet_size
+ @byte_size += strip_partials if partial_length?
parse_content
return self
end
-
-
def parse_content
stream.seek(byte_size,IO::SEEK_CUR)
end
private
+ def strip_partials
+ package_start = @stream.pos
+ start = package_start + @byte_size
+ partial_size = 0
+
+ @stream = ZappableByteStream.new(stream)
+
+ while partial_length? do
+ @stream.pos= start+partial_size
+
+ size = new_packet_size
+ partial_size += size[:s]
+
+ #remove the header packets from the stream => subclasses wont have to worry abouth this
+ @stream.zap(size[:h])
+ end
+ @stream.pos= package_start
+ partial_size
+ end
def partial_length?
partial_length
end
@@ -79,13 +73,13 @@ module FPG
end
end
def new_packet_size
- self.partial_length= false
+ @partial_length= false
first = stream.getbyte
return { :s => first, :h => 1 } if first < 192
- return { :s => ((firs<t-192)<<8)+stream.getbyte+192, :h => 2 } if first < 224
- return { :s => (first+stream.read(3)).unpack("N")[0], :h => 4 } if first == 255
- self.partial_length= true
- return { :s => 1<<(first&0x1f), :h => 1 }
+ return { :s => (((first-192)<<8)+stream.getbyte+192), :h => 2 } if first < 224
+ return { :s => ((first+stream.read(3)).unpack("N")[0]), :h => 4 } if first == 255
+ @partial_length= true
+ return { :s => (1<<(first&0x1f)), :h => 1 }
end
def old_packet_size(tag)
return stream.getbyte if tag == 0
diff --git a/spec/zappable_byte_stream_spec.rb b/spec/zappable_byte_stream_spec.rb
index 129fa75..93574bf 100644
--- a/spec/zappable_byte_stream_spec.rb
+++ b/spec/zappable_byte_stream_spec.rb
@@ -44,14 +44,31 @@ describe ZappableByteStream do
@stream.read(4)
@stream.zap(2)
@stream.pos=3
+ @stream.read(2).should == "23"
+ end
+ it "should be able to set the position on first zapped byte" do
+ @stream.read(4)
+ @stream.zap(2)
+ @stream.pos=2
@stream.read(2).should == "12"
end
it "should be able to seek in regard to zapped bytes" do
@stream.read(4)
@stream.zap(2)
- @stream.pos=2
+ @stream.pos=1
@stream.seek(1,IO::SEEK_CUR)
@stream.read(2).should == "12"
end
+ it "should not break when positioned on zapped byte" do
+ @stream.read(3)
+ @stream.zap
+ @stream.pos=2
+ @stream.read(2).should == "t1"
+ end
+ it "should adapt position when zapping bytes" do
+ @stream.pos= 2
+ @stream.zap
+ @stream.pos.should == 1
+ end
end