Class: Hexdump::Hexdump
- Inherits:
-
Object
- Object
- Hexdump::Hexdump
- Defined in:
- lib/hexdump/hexdump.rb
Overview
Handles the parsing of data and formatting of the hexdump.
Constant Summary collapse
- DEFAULT_COLUMNS =
Default number of columns
16
- BASES =
Numeric bases and their formatting classes.
{ 16 => Numeric::Hexadecimal, 10 => Numeric::Decimal, 8 => Numeric::Octal, 2 => Numeric::Binary }
Reader Configuration collapse
-
#length ⇒ Integer?
The optional length of data to read.
-
#offset ⇒ Integer?
The optional offset to start the index at.
-
#repeating ⇒ Boolean
(also: #repeating?)
Controls whether repeating duplicate rows will be omitted with a
*
. -
#type ⇒ Type
The word type to decode the byte stream as.
-
#zero_pad ⇒ Boolean
(also: #zero_pad?)
Controls whether to zero-pad the data so it aligns with the type's size.
Numeric Configuration collapse
-
#base ⇒ 16, ...
The base to dump words as.
-
#columns ⇒ Integer
The number of columns per hexdump line.
-
#group_columns ⇒ Integer?
The number of columns to group together.
Index Configuration collapse
-
#index_base ⇒ 16, ...
The base to format the index column as.
-
#index_offset ⇒ Integer?
Starts the index at the given offset.
Characters Configuration collapse
-
#chars_column ⇒ Boolean
(also: #chars_column?)
Controls whether to display the characters column.
-
#encoding ⇒ Encoding?
The encoding to use when decoding characters.
-
#group_chars ⇒ Integer?
Groups the characters together into groups.
Instance Attribute Summary collapse
-
#chars ⇒ Chars?
readonly
The characters formatter.
-
#index ⇒ Numeric::Hexadecimal, ...
readonly
The format of the index number.
-
#numeric ⇒ Numeric::Hexadecimal, ...
readonly
The numeric base format.
-
#reader ⇒ Reader
readonly
The reader object.
Theme Configuration collapse
-
#theme {|theme| ... } ⇒ Theme?
The hexdump theme.
-
#theme? ⇒ Boolean
Determines if hexdump styling/highlighting has been enabled.
Formatting Methods collapse
-
#dump(data) ⇒ String
Outputs the hexdump to a String.
-
#each_formatted_row(data, ansi: theme?, , **kwargs) {|index, numeric, chars| ... } ⇒ String, Enumerator
Enumerates each formatted row of hexdumped data.
-
#each_line(data, **kwargs) {|line| ... } ⇒ Enumerator?
Enumerates over each line in the hexdump.
-
#each_non_repeating_row(data) {|index, numeric, chars| ... } ⇒ Integer, Enumerator
Enumerates each non-repeating row of hexdumped data.
-
#each_row(data) {|index, values, chars| ... } ⇒ Integer, Enumerator
Enumerates each row of values read from the given data.
-
#each_slice(data) {|slice| ... } ⇒ Enumerator
Enumerates over each slice of read values.
-
#hexdump(data, output: $stdout) ⇒ nil
Prints the hexdump.
Instance Method Summary collapse
-
#initialize(type: :byte, offset: nil, length: nil, zero_pad: false, repeating: false, columns: nil, group_columns: nil, group_chars: nil, base: nil, index_base: 16, index_offset: nil, chars_column: true, encoding: nil, style: nil, highlights: nil) {|self| ... } ⇒ Hexdump
constructor
Initializes a hexdump format.
Constructor Details
#initialize(type: :byte, offset: nil, length: nil, zero_pad: false, repeating: false, columns: nil, group_columns: nil, group_chars: nil, base: nil, index_base: 16, index_offset: nil, chars_column: true, encoding: nil, style: nil, highlights: nil) {|self| ... } ⇒ Hexdump
Initializes a hexdump format.
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 |
# File 'lib/hexdump/hexdump.rb', line 143 def initialize(type: :byte, offset: nil, length: nil, zero_pad: false, repeating: false, columns: nil, group_columns: nil, group_chars: nil, base: nil, index_base: 16, index_offset: nil, chars_column: true, encoding: nil, style: nil, highlights: nil) # reader options self.type = type self.offset = offset self.length = length self.zero_pad = zero_pad self.repeating = repeating # numeric formatting options self.base = base if base self.columns = columns self.group_columns = group_columns # index options self.index_base = index_base self.index_offset = index_offset || offset # chars formatting options self.encoding = encoding self.chars_column = chars_column self.group_chars = group_chars @theme = if (style.kind_of?(Hash) || highlights.kind_of?(Hash)) Theme.new( style: style || {}, highlights: highlights || {} ) end yield self if block_given? @reader = Reader.new(@type, offset: @offset, length: @length, zero_pad: @zero_pad) # default the numeric base @base ||= case @type when Type::Float, Type::Char, Type::UChar then 10 else 16 end # default the number of columns based on the type's size @columns ||= (DEFAULT_COLUMNS / @type.size) @index = BASES.fetch(@index_base).new(TYPES[:uint32]) @numeric = BASES.fetch(@base).new(@type) case @type when Type::Char, Type::UChar # display characters inline for the :char and :uchar type, and disable # the characters column @numeric = Numeric::CharOrInt.new(@numeric,@encoding) @chars = nil @chars_column = false else @chars = Chars.new(@encoding) if @chars_column end end |
Instance Attribute Details
#base ⇒ 16, ...
The base to dump words as.
272 273 274 |
# File 'lib/hexdump/hexdump.rb', line 272 def base @base end |
#chars ⇒ Chars? (readonly)
The characters formatter.
56 57 58 |
# File 'lib/hexdump/hexdump.rb', line 56 def chars @chars end |
#chars_column ⇒ Boolean Also known as: chars_column?
Controls whether to display the characters column.
382 383 384 |
# File 'lib/hexdump/hexdump.rb', line 382 def chars_column @chars_column end |
#columns ⇒ Integer
The number of columns per hexdump line.
299 300 301 |
# File 'lib/hexdump/hexdump.rb', line 299 def columns @columns end |
#encoding ⇒ Encoding?
The encoding to use when decoding characters.
355 356 357 |
# File 'lib/hexdump/hexdump.rb', line 355 def encoding @encoding end |
#group_chars ⇒ Integer?
Groups the characters together into groups.
391 392 393 |
# File 'lib/hexdump/hexdump.rb', line 391 def group_chars @group_chars end |
#group_columns ⇒ Integer?
The number of columns to group together.
306 307 308 |
# File 'lib/hexdump/hexdump.rb', line 306 def group_columns @group_columns end |
#index ⇒ Numeric::Hexadecimal, ... (readonly)
The format of the index number.
43 44 45 |
# File 'lib/hexdump/hexdump.rb', line 43 def index @index end |
#index_base ⇒ 16, ...
The base to format the index column as.
317 318 319 |
# File 'lib/hexdump/hexdump.rb', line 317 def index_base @index_base end |
#index_offset ⇒ Integer?
Starts the index at the given offset.
344 345 346 |
# File 'lib/hexdump/hexdump.rb', line 344 def index_offset @index_offset end |
#length ⇒ Integer?
The optional length of data to read.
226 227 228 |
# File 'lib/hexdump/hexdump.rb', line 226 def length @length end |
#numeric ⇒ Numeric::Hexadecimal, ... (readonly)
The numeric base format.
51 52 53 |
# File 'lib/hexdump/hexdump.rb', line 51 def numeric @numeric end |
#offset ⇒ Integer?
The optional offset to start the index at.
219 220 221 |
# File 'lib/hexdump/hexdump.rb', line 219 def offset @offset end |
#reader ⇒ Reader (readonly)
The reader object.
35 36 37 |
# File 'lib/hexdump/hexdump.rb', line 35 def reader @reader end |
#repeating ⇒ Boolean Also known as: repeating?
Controls whether repeating duplicate rows will be omitted with a *
.
242 243 244 |
# File 'lib/hexdump/hexdump.rb', line 242 def repeating @repeating end |
#type ⇒ Type
The word type to decode the byte stream as.
212 213 214 |
# File 'lib/hexdump/hexdump.rb', line 212 def type @type end |
#zero_pad ⇒ Boolean Also known as: zero_pad?
Controls whether to zero-pad the data so it aligns with the type's size.
233 234 235 |
# File 'lib/hexdump/hexdump.rb', line 233 def zero_pad @zero_pad end |
Instance Method Details
#dump(data) ⇒ String
Caution: this method appends each line of the hexdump to a String, and that String can grow quite large and consume a lot of memory.
Outputs the hexdump to a String.
770 771 772 773 774 |
# File 'lib/hexdump/hexdump.rb', line 770 def dump(data) String.new.tap do |string| hexdump(data, output: string) end end |
#each_formatted_row(data, ansi: theme?, , **kwargs) {|index, numeric, chars| ... } ⇒ String, Enumerator
Enumerates each formatted row of hexdumped data.
600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 |
# File 'lib/hexdump/hexdump.rb', line 600 def each_formatted_row(data, ansi: theme?, **kwargs) return enum_for(__method__,data, ansi: ansi) unless block_given? format_index = lambda { |index| formatted = @index % index formatted = @theme.index.apply(formatted) if ansi formatted } blank = ' ' * @numeric.width format_numeric = lambda { |value| if value formatted = @numeric % value formatted = @theme.numeric.apply(formatted) if ansi formatted else blank end } # cache the formatted numbers for 8bit and 16bit values numeric_cache = if @type.size <= 2 Hash.new do |hash,value| hash[value] = format_numeric.call(value) end else format_numeric end if @chars format_chars = lambda { |chars| formatted = @chars.scrub(chars.join) formatted = @theme.chars.apply(formatted) if ansi formatted } end enum = if @repeating then each_row(data) else each_non_repeating_row(data) end index = enum.each do |index,numeric,chars=nil| if index == '*' yield index else formatted_index = format_index[index] formatted_numbers = numeric.map { |value| numeric_cache[value] } formatted_chars = if @chars if @group_chars chars.join.chars.each_slice(@group_chars).map(&format_chars) else format_chars.call(chars) end end yield formatted_index, formatted_numbers, formatted_chars end end return format_index[index] end |
#each_line(data, **kwargs) {|line| ... } ⇒ Enumerator?
Enumerates over each line in the hexdump.
684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 |
# File 'lib/hexdump/hexdump.rb', line 684 def each_line(data,**kwargs) return enum_for(__method__,data,**kwargs) unless block_given? join_numeric = if @group_columns lambda { |numeric| numeric.each_slice(@group_columns).map { |numbers| numbers.join(' ') }.join(' ') } else lambda { |numeric| numeric.join(' ') } end index = each_formatted_row(data,**kwargs) do |index,numeric,chars=nil| if index == '*' yield "#{index}#{$/}" else numeric_column = join_numeric.call(numeric) if numeric.length < @columns missing_columns = (@columns - numeric.length) column_width = @numeric.width + 1 spaces = (missing_columns * column_width) spaces += ((missing_columns / @group_columns) - 1) if @group_columns numeric_column << ' ' * spaces end line = if @chars if @group_chars chars = chars.join('|') end "#{index} #{numeric_column} |#{chars}|#{$/}" else "#{index} #{numeric_column}#{$/}" end yield line end end yield "#{index}#{$/}" return nil end |
#each_non_repeating_row(data) {|index, numeric, chars| ... } ⇒ Integer, Enumerator
Enumerates each non-repeating row of hexdumped data.
548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 |
# File 'lib/hexdump/hexdump.rb', line 548 def each_non_repeating_row(data) return enum_for(__method__,data) unless block_given? previous_row = nil is_repeating = false each_row(data) do |index,*row| if row == previous_row unless is_repeating yield '*' is_repeating = true end else if is_repeating previous_row = nil is_repeating = false end yield index, *row previous_row = row end end end |
#each_row(data) {|index, values, chars| ... } ⇒ Integer, Enumerator
Enumerates each row of values read from the given data.
497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 |
# File 'lib/hexdump/hexdump.rb', line 497 def each_row(data,&block) return enum_for(__method__,data) unless block_given? index = @index_offset || 0 chars = nil each_slice(data) do |slice| numeric = [] chars = [] if @chars next_index = index slice.each do |(raw,value)| numeric << value chars << raw if @chars next_index += raw.length end yield index, numeric, chars index = next_index end return index end |
#each_slice(data) {|slice| ... } ⇒ Enumerator
Enumerates over each slice of read values.
470 471 472 |
# File 'lib/hexdump/hexdump.rb', line 470 def each_slice(data,&block) @reader.each(data).each_slice(@columns,&block) end |
#hexdump(data, output: $stdout) ⇒ nil
Prints the hexdump.
745 746 747 748 749 750 751 752 753 754 755 |
# File 'lib/hexdump/hexdump.rb', line 745 def hexdump(data, output: $stdout) unless output.respond_to?(:<<) raise(ArgumentError,"output must support the #<< method") end ansi = theme? && output.tty? each_line(data, ansi: ansi) do |line| output << line end end |
#theme {|theme| ... } ⇒ Theme?
The hexdump theme.
441 442 443 444 445 446 447 448 |
# File 'lib/hexdump/hexdump.rb', line 441 def theme(&block) if block @theme ||= Theme.new @theme.tap(&block) else @theme end end |
#theme? ⇒ Boolean
Determines if hexdump styling/highlighting has been enabled.
423 424 425 |
# File 'lib/hexdump/hexdump.rb', line 423 def theme? !@theme.nil? end |