class Hexdump::Reader
@api private
@since 1.0.0
Attributes
Controls control many bytes to read.
@return [Integer, nil]
Controls whether to offset N number of bytes before starting to read data.
@return [Integer, nil]
The type to decode the data as.
@return [Type]
Public Class Methods
Initializes the reader.
@param [Type] type
The type to decode the data as.
@param [Integer, nil] offset
Controls whether to offset N number of bytes before starting to read data.
@param [Integer, nil] length
Controls control many bytes to read.
@param [Boolean] zero_pad
Controls whether the remaining data will be padded with zeros.
# File lib/hexdump/reader.rb, line 43 def initialize(type, offset: nil, length: nil, zero_pad: false) @type = type @offset = offset @length = length @zero_pad = zero_pad end
Public Instance Methods
@param [#each_byte] data
@yield [raw, value]
@yieldparam [String] raw
@yieldparam [Integer, Float, nil] value
@return [Enumerator]
# File lib/hexdump/reader.rb, line 298 def each(data,&block) return enum_for(__method__,data) unless block case @type when Type::UInt each_uint(data,&block) when Type::Float each_float(data,&block) when Type::Int each_int(data,&block) else raise(TypeError,"unsupported type: #{@type.inspect}") end end
Reads each byte from the given data.
@yield [byte]
@yieldparam [Integer] byte
@return [Enumerator]
@raise [ArgumentError]
# File lib/hexdump/reader.rb, line 65 def each_byte(data) return enum_for(__method__,data) unless block_given? unless data.respond_to?(:each_byte) raise(ArgumentError,"the given data must respond to #each_byte") end count = 0 data.each_byte do |b| count += 1 # offset the first @offset number of bytes if @offset.nil? || count > @offset yield b end # stop reading after @length number of bytes break if @length && count >= @length end end
@param [#each_byte] data
@yield [raw, float]
@yieldparam [String] raw
@yieldparam [Float, nil] float
@return [Enumerator]
# File lib/hexdump/reader.rb, line 260 def each_float(data) return enum_for(__method__,data) unless block_given? pack_format = case @type.endian when :little case @type.size when 4 then 'e' when 8 then 'E' else raise(TypeError,"unsupported type size #{@type.size} for #{@type.name}") end when :big case @type.size when 4 then 'g' when 8 then 'G' else raise(TypeError,"unsupported type size #{@type.size} for #{@type.name}") end else raise(TypeError,"unsupported endian #{@type.endian} for #{@type.name}") end each_slice(data) do |slice| yield slice, slice.unpack1(pack_format) end end
@param [#each_byte] data
@yield [raw, int]
@yieldparam [String] raw
@yieldparam [Integer, nil] int
@return [Enumerator]
# File lib/hexdump/reader.rb, line 213 def each_int(data) return enum_for(__method__,data) unless block_given? pack_format = case @type.size when 1 'c' when 2 case @type.endian when :little then 's<' when :big then 's>' else raise(TypeError,"unsupported endian #{@type.endian} for #{@type.name}") end when 4 case @type.endian when :little then 'l<' when :big then 'l>' else raise(TypeError,"unsupported endian #{@type.endian} for #{@type.name}") end when 8 case @type.endian when :little then 'q<' when :big then 'q>' else raise(TypeError,"unsupported endian #{@type.endian} for #{@type.name}") end else raise(TypeError,"unsupported type size #{@type.size} for #{@type.name}") end each_slice(data) do |slice| yield slice, slice.unpack1(pack_format) end end
Reads each string of the same number of bytes as the {#type}'s {Type#size size}.
@param [#each_byte] data
@yield [slice]
@yieldparam [String] slice
@raise [ArgumentError]
# File lib/hexdump/reader.rb, line 99 def each_slice(data) return enum_for(__method__,data) unless block_given? unless data.respond_to?(:each_byte) raise(ArgumentError,"the given data must respond to #each_byte") end count = 0 if @type.size == 1 each_byte(data) do |b| yield b.chr end else buffer = String.new("\0" * @type.size, capacity: @type.size, encoding: Encoding::BINARY) index = 0 each_byte(data) do |b| buffer[index] = b.chr(Encoding::BINARY) index += 1 if index >= @type.size yield buffer.dup index = 0 end end if index > 0 if @zero_pad # zero pad the rest of the buffer (index..(@type.size - 1)).each do |i| buffer[i] = "\0" end yield buffer else # yield the reamining partial buffer yield buffer[0,index] end end end end
@param [#each_byte] data
@yield [raw, uint]
@yieldparam [String] raw
@yieldparam [Integer, nil] uint
@return [Enumerator]
@raise [ArgumentError]
# File lib/hexdump/reader.rb, line 156 def each_uint(data,&block) return enum_for(__method__,data) unless block_given? unless data.respond_to?(:each_byte) raise(ArgumentError,"the given data must respond to #each_byte") end if @type.size == 1 each_byte(data) do |b| yield b.chr, b end else pack_format = case @type.size when 1 'c' when 2 case @type.endian when :little then 'S<' when :big then 'S>' else raise(TypeError,"unsupported endian #{@type.endian} for #{@type.name}") end when 4 case @type.endian when :little then 'L<' when :big then 'L>' else raise(TypeError,"unsupported endian #{@type.endian} for #{@type.name}") end when 8 case @type.endian when :little then 'Q<' when :big then 'Q>' else raise(TypeError,"unsupported endian #{@type.endian} for #{@type.name}") end else raise(TypeError,"unsupported type size #{@type.size} for #{@type.name}") end each_slice(data) do |slice| yield slice, slice.unpack1(pack_format) end end end
# File lib/hexdump/reader.rb, line 50 def zero_pad? @zero_pad end