class Kaitai::Struct::Visualizer::Node
Attributes
children[R]
id[RW]
level[R]
parent[RW]
pos1[R]
pos2[R]
type[RW]
value[R]
Public Class Methods
new(tree, value, level, value_method = nil, pos1 = nil, pos2 = nil)
click to toggle source
# File lib/kaitai/struct/visualizer/node.rb, line 17 def initialize(tree, value, level, value_method = nil, pos1 = nil, pos2 = nil) @tree = tree @value = value @level = level @value_method = value_method unless pos1.nil? or pos2.nil? @pos1 = pos1 @pos2 = pos2 end @open = false @explored = false @children = [] end
Public Instance Methods
add(child)
click to toggle source
# File lib/kaitai/struct/visualizer/node.rb, line 34 def add(child) @children << child child.parent = self end
close()
click to toggle source
# File lib/kaitai/struct/visualizer/node.rb, line 71 def close @open = false end
detect_str_mode()
click to toggle source
Empirically detects a mode that would be best to show a designated string
# File lib/kaitai/struct/visualizer/node.rb, line 142 def detect_str_mode if @value.encoding == Encoding::ASCII_8BIT :hex else :str_esc end end
draw(ui)
click to toggle source
# File lib/kaitai/struct/visualizer/node.rb, line 75 def draw(ui) print ' ' * level print(if @value.nil? '[?]' elsif open? '[-]' elsif openable? '[+]' else '[.]' end) print " #{@id}" pos = 2 * level + 4 + @id.length if open? or not openable? if @value.is_a?(Fixnum) or @value.is_a?(Bignum) or @value.is_a?(Float) print " = #{@value}" elsif @value.is_a?(Symbol) print " = #{@value}" elsif @value.is_a?(String) print ' = ' pos += 3 @str_mode = detect_str_mode unless @str_mode max_len = @tree.tree_width - pos case @str_mode when :str v = @value.encode('UTF-8') s = v[0, max_len] when :str_esc v = @value.encode('UTF-8') s = v.inspect[0, max_len] when :hex s = first_n_bytes_dump(@value, max_len / 3 + 1) else raise "Invalid str_mode: #{@str_mode.inspect}" end if s.length > max_len s = s[0, max_len - 1] s += '…' end print s elsif @value === true or @value === false print " = #{@value}" elsif @value.nil? print " = null" elsif @value.is_a?(Array) printf ' (%d = 0x%x entries)', @value.size, @value.size end end puts end
explore()
click to toggle source
# File lib/kaitai/struct/visualizer/node.rb, line 164 def explore return if @explored if @value.nil? @value = @parent.value.send(@value_method) end @explored = true if @value.is_a?(Fixnum) or @value.is_a?(Bignum) or @value.is_a?(Float) or @value.is_a?(String) or @value == true or @value == false or @value.nil? or @value.is_a?(Symbol) clean_id = @id[0] == '@' ? @id[1..-1] : @id debug_el = @parent.value._debug[clean_id] #raise "Unable to get debugging aid for: #{@parent.value._debug.inspect} using ID '#{clean_id}'" unless debug_el if debug_el @pos1 = debug_el[:start] @pos2 = debug_el[:end] end elsif @value.is_a?(Array) # Bail out early for empty array: it doesn't have proper # debugging aids structure anyway return if @value.empty? clean_id = @id[0] == '@' ? @id[1..-1] : @id debug_el = @parent.value._debug[clean_id] raise "Unable to get debugging aid for array: #{@parent.value._debug.inspect} using ID '#{clean_id}'" unless debug_el aid = debug_el[:arr] raise "Unable to get debugging aid for array: #{debug_el.inspect}" unless aid max_val_digits = @value.size.to_s.size fmt = "%#{max_val_digits}d" @value.each_with_index { |el, i| aid_el = aid[i] || {} n = Node.new(@tree, el, level + 1, nil, aid_el[:start], aid_el[:end]) n.id = sprintf(fmt, i) add(n) } else # Gather seq attributes @value.class::SEQ_FIELDS.each { |k| el = @value.instance_eval("@#{k}") aid = @value._debug[k] if aid aid_s = aid[:start] aid_e = aid[:end] else #raise "Unable to get debugging aid for '#{k}'" aid_s = nil aid_e = nil end unless el.nil? n = Node.new(@tree, el, level + 1, nil, aid_s, aid_e) n.id = k n.type = :seq add(n) end } attrs = Set.new(@value.class::SEQ_FIELDS) # Gather instances common_meths = Set.new @value.class.ancestors.each { |cl| next if cl == @value.class common_meths.merge(cl.instance_methods) } inst_meths = Set.new(@value.public_methods) - common_meths inst_meths.each { |meth| k = meth.to_s next if k =~ /^_/ or attrs.include?(k) n = Node.new(@tree, nil, level + 1, meth) n.id = k n.type = :instance add(n) } end end
first_n_bytes_dump(s, n)
click to toggle source
# File lib/kaitai/struct/visualizer/node.rb, line 129 def first_n_bytes_dump(s, n) i = 0 r = '' s.each_byte { |x| r << sprintf('%02x ', x) i += 1 break if i >= n } r end
height()
click to toggle source
Determine total height of an element, including all children if it's open and visible
# File lib/kaitai/struct/visualizer/node.rb, line 252 def height if @open r = 1 @children.each { |n| r += n.height } r else 1 end end
hex?()
click to toggle source
# File lib/kaitai/struct/visualizer/node.rb, line 53 def hex? @value.is_a?(String) end
io()
click to toggle source
# File lib/kaitai/struct/visualizer/node.rb, line 150 def io return @io if @io if @parent.nil? @io = @value._io else obj = @parent while not obj.value.respond_to?(:_io) obj = obj.parent end @io = obj.value._io end end
last_descendant()
click to toggle source
Find out last (deepest) descendant of current node
# File lib/kaitai/struct/visualizer/node.rb, line 264 def last_descendant n = self while n.open? n = n.children.last end n end
open()
click to toggle source
# File lib/kaitai/struct/visualizer/node.rb, line 65 def open return unless openable? explore @open = true if @explored end
open?()
click to toggle source
# File lib/kaitai/struct/visualizer/node.rb, line 39 def open?; @open; end
openable?()
click to toggle source
# File lib/kaitai/struct/visualizer/node.rb, line 41 def openable? not ( @value.is_a?(Fixnum) or @value.is_a?(Bignum) or @value.is_a?(Float) or @value.is_a?(String) or @value.is_a?(Symbol) or @value === true or @value === false ) end
toggle()
click to toggle source
# File lib/kaitai/struct/visualizer/node.rb, line 57 def toggle if @open close else open end end