kaitai-struct-visualizer 0.5 → 0.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,253 +1,234 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'benchmark'
2
4
 
3
5
  require 'kaitai/struct/visualizer/version'
4
6
  require 'kaitai/struct/visualizer/node'
5
7
  require 'kaitai/struct/visualizer/hex_viewer'
8
+ require 'kaitai/struct/visualizer/ks_error_matcher'
6
9
 
7
10
  module Kaitai::Struct::Visualizer
8
- class Tree
9
- def initialize(ui, st)
10
- @ui = ui
11
- @st = st
12
- @root = Node.new(self, st, 0)
13
- @root.id = '[root]'
14
- @max_scr_ln = @ui.rows - 3
15
-
16
- @hv_shift_x = @ui.cols - HexViewer.line_width - 1
17
-
18
- @cur_io = nil
19
- @hv = HexViewer.new(ui, nil, @hv_shift_x, self)
20
- @hv_hidden = false
21
-
22
- @cur_line = 0
23
- @cur_shift = 0
24
- @do_exit = false
25
- end
11
+ class Tree
12
+ def initialize(ui, st)
13
+ @ui = ui
14
+ @st = st
15
+ @root = Node.new(self, st, 0)
16
+ @root.id = '[root]'
17
+
18
+ @cur_io = nil
19
+ @hv = HexViewer.new(ui, nil, self)
20
+ @hv_hidden = false
21
+
22
+ recalc_sizes
23
+
24
+ @cur_line = 0
25
+ @cur_shift = 0
26
+ @do_exit = false
27
+
28
+ @ui.on_resize = proc { |redraw_needed|
29
+ recalc_sizes
30
+ redraw if redraw_needed
31
+ @hv.redraw if redraw_needed
32
+ }
33
+ end
26
34
 
27
- def run
28
- c = nil
29
- loop {
30
- t = redraw
35
+ def recalc_sizes
36
+ @max_scr_ln = @ui.rows - 3
37
+ @hv.shift_x = @ui.cols - HexViewer.line_width - 1
38
+ end
31
39
 
32
- if @cur_node.nil? and not @cur_line.nil?
33
- # gone beyond the end of the tree
34
- @cur_line = @root.height - 1
35
- clamp_cursor
36
- redraw
37
- end
40
+ def run
41
+ loop do
42
+ t = redraw
43
+
44
+ if @cur_node.nil? && !@cur_line.nil?
45
+ # gone beyond the end of the tree
46
+ @cur_line = @root.height - 1
47
+ clamp_cursor
48
+ redraw
49
+ end
38
50
 
39
- raise '@cur_line is undetermined' if @cur_line.nil?
40
- raise '@cur_node is undetermined' if @cur_node.nil?
51
+ raise '@cur_line is undetermined' if @cur_line.nil?
52
+ raise '@cur_node is undetermined' if @cur_node.nil?
41
53
 
42
- thv = Benchmark.realtime {
43
- unless @hv_hidden
44
- hv_update_io
54
+ thv = Benchmark.realtime do
55
+ unless @hv_hidden
56
+ hv_update_io
45
57
 
46
- unless @cur_node.pos1.nil?
47
- if (@hv.addr < @cur_node.pos1) or (@hv.addr >= @cur_node.pos2)
58
+ if !@cur_node.pos1.nil? && ((@hv.addr < @cur_node.pos1) || (@hv.addr >= @cur_node.pos2))
48
59
  @hv.addr = @cur_node.pos1
49
60
  @hv.ensure_visible
50
61
  end
51
- end
52
62
 
53
- @hv.redraw
54
- regs = highlight_regions(4)
55
- @hv.highlight(regs)
63
+ @hv.redraw
64
+ regs = highlight_regions(4)
65
+ @hv.highlight(regs)
66
+ end
56
67
  end
57
- }
58
68
 
59
- @ui.goto(0, @max_scr_ln + 1)
60
- printf "all: %d, tree: %d, tree_draw: %d, hexview: %d, ln: %d, ", (t + thv) * 1e6, t * 1e6, @draw_time * 1e6, thv * 1e6, @ln
61
- puts "highlight = #{@cur_node.pos1}..#{@cur_node.pos2}"
62
- #puts "keypress: #{c.inspect}"
63
-
64
- begin
65
- process_keypress
66
- rescue EOFError => e
67
- @ui.message_box_exception(e)
68
- rescue Kaitai::Struct::Stream::UnexpectedDataError => e
69
- @ui.message_box_exception(e)
70
- end
69
+ @ui.goto(0, @max_scr_ln + 1)
70
+ printf 'all: %d, tree: %d, tree_draw: %d, hexview: %d, ln: %d, ', (t + thv) * 1e6, t * 1e6, @draw_time * 1e6, thv * 1e6, @ln
71
+ puts "highlight = #{@cur_node.pos1}..#{@cur_node.pos2}"
72
+ # puts "keypress: #{c.inspect}"
71
73
 
72
- return if @do_exit
74
+ begin
75
+ process_keypress
76
+ rescue Kaitai::Struct::Visualizer::KSErrorMatcher => e
77
+ @ui.message_box_exception(e)
78
+ end
73
79
 
74
- clamp_cursor
75
- }
76
- end
80
+ return if @do_exit
77
81
 
78
- def process_keypress
79
- c = @ui.read_char_mapped
80
- case c
81
- when :up_arrow
82
- @cur_line -= 1
83
- @cur_node = nil
84
- when :down_arrow
85
- @cur_line += 1
86
- @cur_node = nil
87
- when :left_arrow
88
- if @cur_node.open?
89
- @cur_node.close
90
- else
91
- par = @cur_node.parent
92
- if par
93
- @cur_line = nil
94
- @cur_node = par
95
- end
82
+ clamp_cursor
96
83
  end
97
- when :right_arrow
98
- if @cur_node.openable?
84
+ end
85
+
86
+ def process_keypress
87
+ c = @ui.read_char_mapped
88
+ case c
89
+ when :up_arrow
90
+ @cur_line -= 1
91
+ @cur_node = nil
92
+ when :down_arrow
93
+ @cur_line += 1
94
+ @cur_node = nil
95
+ when :left_arrow
99
96
  if @cur_node.open?
100
- @cur_line += 1
101
- @cur_node = nil
97
+ @cur_node.close
102
98
  else
103
- @cur_node.open
99
+ par = @cur_node.parent
100
+ if par
101
+ @cur_line = nil
102
+ @cur_node = par
103
+ end
104
104
  end
105
- end
106
- when :home
107
- @cur_line = @cur_shift = 0
108
- @cur_node = nil
109
- when :end
110
- @cur_line = @root.height - 1
111
- @cur_node = nil
112
- when :pg_up
113
- @cur_line -= 20
114
- @cur_node = nil
115
- when :pg_dn
116
- @cur_line += 20
117
- @cur_node = nil
118
- when :enter
119
- if @cur_node.hex?
120
- @ui.clear
121
- hv = HexViewer.new(@ui, @cur_node.value)
122
- hv.redraw
123
- hv.run
105
+ when :right_arrow
106
+ if @cur_node.openable?
107
+ if @cur_node.open?
108
+ @cur_line += 1
109
+ @cur_node = nil
110
+ else
111
+ @cur_node.open
112
+ end
113
+ end
114
+ when :home
115
+ @cur_line = @cur_shift = 0
116
+ @cur_node = nil
117
+ when :end
118
+ @cur_line = @root.height - 1
119
+ @cur_node = nil
120
+ when :pg_up
121
+ @cur_line -= 20
122
+ @cur_node = nil
123
+ when :pg_dn
124
+ @cur_line += 20
125
+ @cur_node = nil
126
+ when :enter
127
+ if @cur_node.hex?
128
+ @ui.clear
129
+ hv = HexViewer.new(@ui, @cur_node.value)
130
+ hv.redraw
131
+ hv.run
132
+ @ui.clear
133
+ redraw
134
+ else
135
+ @cur_node.toggle
136
+ end
137
+ when :tab
138
+ @hv.run
139
+ when 'H'
140
+ @hv_hidden = !@hv_hidden
124
141
  @ui.clear
125
142
  redraw
126
- else
127
- @cur_node.toggle
143
+ when 'q'
144
+ @do_exit = true
128
145
  end
129
- when :tab
130
- @hv.run
131
- when 'H'
132
- @hv_hidden = !@hv_hidden
133
- @ui.clear
134
- redraw
135
- when 'q'
136
- @do_exit = true
137
146
  end
138
- end
139
147
 
140
- def clamp_cursor
141
- if @cur_line
142
- @cur_line = 0 if @cur_line < 0
148
+ def clamp_cursor
149
+ return unless @cur_line
143
150
 
144
- if @cur_line - @cur_shift < 0
145
- @cur_shift = @cur_line
146
- end
147
- if @cur_line - @cur_shift > @max_scr_ln
148
- @cur_shift = @cur_line - @max_scr_ln
151
+ @cur_line = 0 if @cur_line.negative?
152
+
153
+ @cur_shift = @cur_line if (@cur_line - @cur_shift).negative?
154
+ @cur_shift = @cur_line - @max_scr_ln if (@cur_line - @cur_shift) > @max_scr_ln
155
+ end
156
+
157
+ def redraw
158
+ @draw_time = 0
159
+ Benchmark.realtime do
160
+ @ui.clear
161
+ @ln = 0
162
+ draw_rec(@root)
149
163
  end
150
164
  end
151
- end
152
165
 
153
- def redraw
154
- @draw_time = 0
155
- Benchmark.realtime {
156
- @ui.clear
157
- @ln = 0
158
- draw_rec(@root)
159
- }
160
- end
166
+ def draw_rec(n)
167
+ scr_ln = @ln - @cur_shift
168
+ return if @cur_node && (scr_ln > @max_scr_ln)
169
+
170
+ if @ln == @cur_line
171
+ # Seeking cur_node by cur_line
172
+ @cur_node = n
173
+ @ui.bg_color = :white
174
+ @ui.fg_color = :black
175
+ elsif @cur_node == n
176
+ # Seeking cur_line by cur_node
177
+ @cur_line = @ln
178
+ @ui.bg_color = :white
179
+ @ui.fg_color = :black
180
+ end
161
181
 
162
- def draw_rec(n)
163
- scr_ln = @ln - @cur_shift
164
- return if @cur_node and scr_ln > @max_scr_ln
165
-
166
- if @ln == @cur_line
167
- # Seeking cur_node by cur_line
168
- @cur_node = n
169
- @ui.bg_color = :gray
170
- @ui.fg_color = :black
171
- elsif @cur_node == n
172
- # Seeking cur_line by cur_node
173
- @cur_line = @ln
174
- @ui.bg_color = :gray
175
- @ui.fg_color = :black
176
- end
182
+ @draw_time += Benchmark.realtime do
183
+ # n.draw(@ui) if scr_ln >= 0
184
+ n.draw(@ui) if (scr_ln >= 0) && (scr_ln <= @max_scr_ln)
185
+ end
186
+
187
+ @ui.reset_colors if @ln == @cur_line
188
+ @ln += 1
177
189
 
178
- @draw_time += Benchmark.realtime {
179
- # n.draw(@ui) if scr_ln >= 0
180
- n.draw(@ui) if scr_ln >= 0 and scr_ln <= @max_scr_ln
181
- }
190
+ return unless n.open?
182
191
 
183
- @ui.reset_colors if @ln == @cur_line
184
- @ln += 1
185
- if n.open?
186
- n.children.each { |ch|
192
+ n.children.each do |ch|
187
193
  draw_rec(ch)
188
194
  break if scr_ln > @max_scr_ln
189
- }
195
+ end
190
196
  end
191
- end
192
197
 
193
- def do_exit
194
- @do_exit = true
195
- end
198
+ def do_exit
199
+ @do_exit = true
200
+ end
201
+
202
+ def hv_update_io
203
+ io = @cur_node.io
204
+ return unless io != @cur_io
196
205
 
197
- def hv_update_io
198
- io = @cur_node.io
199
- if io != @cur_io
200
206
  @cur_io = io
201
207
  io.seek(0)
202
208
  buf = io.read_bytes_full
203
209
  @hv.buf = buf
204
210
 
205
- # @hv.redraw
211
+ # @hv.redraw
206
212
  end
207
- end
208
213
 
209
- def highlight_regions(max_levels)
210
- node = @cur_node
211
- r = []
212
- max_levels.times { |i|
213
- return r if node.nil?
214
- r << [node.pos1, node.pos2]
215
- node = node.parent
216
- }
217
- r
218
- end
214
+ def highlight_regions(max_levels)
215
+ node = @cur_node
216
+ r = []
217
+ max_levels.times do |_i|
218
+ return r if node.nil?
219
219
 
220
- def tree_width
221
- if @hv_hidden
222
- @ui.cols
223
- else
224
- @hv_shift_x
220
+ r << [node.pos1, node.pos2]
221
+ node = node.parent
222
+ end
223
+ r
225
224
  end
226
- end
227
225
 
228
- def self.explore_object(obj, level)
229
- root = Node.new(obj, level)
230
- if obj.is_a?(Fixnum) or obj.is_a?(String)
231
- # do nothing else
232
- elsif obj.is_a?(Array)
233
- root = Node.new(obj, level)
234
- obj.each_with_index { |el, i|
235
- n = explore_object(el, level + 1)
236
- n.id = i
237
- root.add(n)
238
- }
239
- else
240
- root = Node.new(obj, level)
241
- obj.instance_variables.each { |k|
242
- k = k.to_s
243
- next if k =~ /^@_/
244
- el = obj.instance_eval(k)
245
- n = explore_object(el, level + 1)
246
- n.id = k
247
- root.add(n)
248
- }
226
+ def tree_width
227
+ if @hv_hidden
228
+ @ui.cols
229
+ else
230
+ @hv.shift_x
231
+ end
249
232
  end
250
- root
251
233
  end
252
234
  end
253
- end
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Kaitai
2
4
  module Struct
3
5
  module Visualizer
4
- VERSION = '0.5'
6
+ VERSION = '0.11'
5
7
  end
6
8
  end
7
9
  end
@@ -1,7 +1,8 @@
1
- require 'tmpdir'
1
+ # frozen_string_literal: true
2
2
 
3
3
  require 'kaitai/struct/visualizer/version'
4
4
  require 'kaitai/tui'
5
+ require 'kaitai/struct/visualizer/parser'
5
6
  require 'kaitai/struct/visualizer/tree'
6
7
 
7
8
  # TODO: should be inside compiled files
@@ -9,39 +10,17 @@ require 'zlib'
9
10
  require 'stringio'
10
11
 
11
12
  module Kaitai::Struct::Visualizer
12
- class Visualizer
13
- def initialize(bin_fn, formats_fn)
14
- @bin_fn = bin_fn
15
- @formats_fn = formats_fn
16
- @primary_format = @formats_fn.shift
13
+ class Visualizer < Parser
14
+ def run
15
+ load_exc = load
17
16
 
18
- main_class_name = compile_format(@primary_format)
17
+ @ui = Kaitai::TUI.new
18
+ @tree = Tree.new(@ui, @data)
19
19
 
20
- @formats_fn.each { |fn|
21
- compile_format(fn)
22
- }
20
+ @tree.redraw
21
+ @ui.message_box_exception(load_exc) if load_exc
23
22
 
24
- main_class = Kernel::const_get(main_class_name)
25
- @data = main_class.from_file(@bin_fn)
26
-
27
- load_exc = nil
28
- begin
29
- @data._read
30
- rescue EOFError => e
31
- load_exc = e
32
- rescue Kaitai::Struct::Stream::UnexpectedDataError => e
33
- load_exc = e
23
+ @tree.run
34
24
  end
35
-
36
- @ui = Kaitai::TUI.new
37
- @tree = Tree.new(@ui, @data)
38
-
39
- @tree.redraw
40
- @ui.message_box_exception(load_exc) if load_exc
41
25
  end
42
-
43
- def run
44
- @tree.run
45
- end
46
- end
47
26
  end
@@ -1,2 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'kaitai/struct/visualizer/version'
2
- require 'kaitai/struct/visualizer/visualizer_main'
4
+ require 'kaitai/struct/visualizer/visualizer'
5
+ require 'kaitai/struct/visualizer/ksy_compiler'