Module | BinaryBlocker |
In: |
lib/blocker.rb
|
# File lib/blocker.rb, line 53 53: def pack_symbols 54: { 55: :int8 => 'c', 56: :uint8 => 'C', 57: :int16 => 's', 58: :uint16 => 'S', 59: :int32 => 'i', 60: :uint32 => 'I', 61: :int64 => 'q', 62: :uint64 => 'Q' 63: } 64: end
To simplify naming of classes and laying out fields in your structures they can be registered:
BinaryBlocker.register_klass(:string, FixedStringEncoder)
# File lib/blocker.rb, line 23 23: def register_klass(sym, klass) 24: @klasses ||= {} 25: @klasses[sym] = klass 26: end
Handy helper method that returns the size of a given pack/unpack format string
# File lib/blocker.rb, line 30 30: def sizeof_format(format) 31: length = 0 32: format.scan(/(\S_?)\s*(\d*)/).each do |directive,count| 33: count = count.to_i 34: count = 1 if count == 0 35: 36: length += case directive 37: when 'A', 'a', 'C', 'c', 'Z', 'x' : count 38: when 'B', 'b' : (count / 8.0).ceil 39: when 'D', 'd', 'E', 'G' : count * 8 40: when 'e', 'F', 'f', 'g' : count * 4 41: when 'H', 'h' : (count / 2.0).ceil 42: when 'I', 'i', 'L', 'l', 'N', 'V' : count * 4 43: when 'n', 'S', 's', 'v' : count * 2 44: when 'Q', 'q' : count * 8 45: when 'X' : count * -1 46: else raise ArgumentError.new("#{directive} is not supported in sizeof_format") 47: end 48: end 49: 50: length 51: end
As we have to process some fields to determine what type they are (that is we sometimes start and half to backup), this routine takes any io (that can be repositioned) and yields to a block — if the block returns not true it will reset the original position of the io stream. If you need to use BinaryBlocker with a non-repositioning stream (like a TCP/IP stream), see the handy BufferedIO class.
# File lib/blocker.rb, line 72 72: def with_guarded_io_pos(io) 73: pos = io.pos 74: status = yield io 75: ensure 76: io.pos = pos unless status 77: end