#!/usr/bin/env ruby module ZPNG module Hexdump def hexdump *args, &block print Hexdump.dump(*args, &block) end class << self def dump data, h = {} offset = h[:offset] || 0 add = h[:add] || 0 size = h[:size] || (data.size-offset) tail = h[:tail] || "\n" width = h[:width] || 0x10 # row width, in bytes h[:show_offset] = true unless h.key?(:show_offset) h[:dedup] = true unless h.key?(:dedup) size = data.size-offset if size+offset > data.size r = ''; prevhex = ''; c = nil; prevdup = false while true ascii = ''; hex = '' width.times do |i| hex << ' ' if i%8==0 && i>0 if c = ((size > 0) && data[offset+i]) hex << "%02x " % c.ord ascii << ((32..126).include?(c.ord) ? c : '.') else hex << ' ' ascii << ' ' end size-=1 end if h[:dedup] && hex == prevhex row = "*" yield(row, offset+add, ascii) if block_given? r << row << "\n" unless prevdup prevdup = true else row = (h[:show_offset] ? ("%08x: " % (offset + add)) : '') + hex + ' |' + ascii + "|" yield(row, offset+add, ascii) if block_given? r << row << "\n" prevdup = false end offset += width prevhex = hex break if size <= 0 end if h[:show_offset] && prevdup row = "%08x: " % (offset + add) yield(row) if block_given? r << row end r.chomp + tail end end end end if $0 == __FILE__ h = {} case ARGV.size when 0 puts "gimme fname [offset] [size]" exit when 1 fname = ARGV[0] when 2 fname = ARGV[0] h[:offset] = ARGV[1].to_i when 3 fname = ARGV[0] h[:offset] = ARGV[1].to_i h[:size] = ARGV[2].to_i end File.open(fname,"rb") do |f| f.seek h[:offset] if h[:offset] @data = f.read(h[:size]) end puts ZPNG::Hexdump.dump(@data) end