hexdump 0.3.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/ChangeLog.md +68 -2
  3. data/Gemfile +1 -0
  4. data/README.md +486 -135
  5. data/benchmark.rb +29 -22
  6. data/lib/hexdump/chars.rb +46 -0
  7. data/lib/hexdump/core_ext/file.rb +68 -6
  8. data/lib/hexdump/core_ext/io.rb +2 -2
  9. data/lib/hexdump/core_ext/kernel.rb +7 -0
  10. data/lib/hexdump/core_ext/string.rb +2 -2
  11. data/lib/hexdump/core_ext/string_io.rb +2 -2
  12. data/lib/hexdump/core_ext.rb +1 -0
  13. data/lib/hexdump/format_string.rb +43 -0
  14. data/lib/hexdump/hexdump.rb +768 -75
  15. data/lib/hexdump/mixin.rb +198 -0
  16. data/lib/hexdump/module_methods.rb +132 -0
  17. data/lib/hexdump/numeric/binary.rb +55 -0
  18. data/lib/hexdump/numeric/char_or_int.rb +90 -0
  19. data/lib/hexdump/numeric/decimal.rb +56 -0
  20. data/lib/hexdump/numeric/exceptions.rb +11 -0
  21. data/lib/hexdump/numeric/hexadecimal.rb +59 -0
  22. data/lib/hexdump/numeric/octal.rb +55 -0
  23. data/lib/hexdump/numeric.rb +5 -0
  24. data/lib/hexdump/reader.rb +314 -0
  25. data/lib/hexdump/theme/ansi.rb +81 -0
  26. data/lib/hexdump/theme/rule.rb +159 -0
  27. data/lib/hexdump/theme.rb +61 -0
  28. data/lib/hexdump/type.rb +232 -0
  29. data/lib/hexdump/types.rb +108 -0
  30. data/lib/hexdump/version.rb +1 -1
  31. data/lib/hexdump.rb +12 -1
  32. data/spec/chars_spec.rb +76 -0
  33. data/spec/core_ext_spec.rb +10 -6
  34. data/spec/hexdump_class_spec.rb +1708 -0
  35. data/spec/hexdump_module_spec.rb +23 -0
  36. data/spec/mixin_spec.rb +37 -0
  37. data/spec/numeric/binary_spec.rb +239 -0
  38. data/spec/numeric/char_or_int_spec.rb +210 -0
  39. data/spec/numeric/decimal_spec.rb +317 -0
  40. data/spec/numeric/hexadecimal_spec.rb +320 -0
  41. data/spec/numeric/octal_spec.rb +239 -0
  42. data/spec/reader_spec.rb +863 -0
  43. data/spec/theme/ansi_spec.rb +242 -0
  44. data/spec/theme/rule_spec.rb +199 -0
  45. data/spec/theme_spec.rb +94 -0
  46. data/spec/type_spec.rb +317 -0
  47. data/spec/types_spec.rb +904 -0
  48. metadata +39 -10
  49. data/.gemtest +0 -0
  50. data/lib/hexdump/dumper.rb +0 -419
  51. data/spec/dumper_spec.rb +0 -329
  52. data/spec/hexdump_spec.rb +0 -30
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hexdump
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Postmodern
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-04-10 00:00:00.000000000 Z
11
+ date: 2021-08-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -34,7 +34,6 @@ extra_rdoc_files:
34
34
  - README.md
35
35
  files:
36
36
  - ".document"
37
- - ".gemtest"
38
37
  - ".github/workflows/ruby.yml"
39
38
  - ".gitignore"
40
39
  - ".rspec"
@@ -48,19 +47,49 @@ files:
48
47
  - gemspec.yml
49
48
  - hexdump.gemspec
50
49
  - lib/hexdump.rb
50
+ - lib/hexdump/chars.rb
51
51
  - lib/hexdump/core_ext.rb
52
52
  - lib/hexdump/core_ext/file.rb
53
53
  - lib/hexdump/core_ext/io.rb
54
+ - lib/hexdump/core_ext/kernel.rb
54
55
  - lib/hexdump/core_ext/string.rb
55
56
  - lib/hexdump/core_ext/string_io.rb
56
- - lib/hexdump/dumper.rb
57
57
  - lib/hexdump/extensions.rb
58
+ - lib/hexdump/format_string.rb
58
59
  - lib/hexdump/hexdump.rb
60
+ - lib/hexdump/mixin.rb
61
+ - lib/hexdump/module_methods.rb
62
+ - lib/hexdump/numeric.rb
63
+ - lib/hexdump/numeric/binary.rb
64
+ - lib/hexdump/numeric/char_or_int.rb
65
+ - lib/hexdump/numeric/decimal.rb
66
+ - lib/hexdump/numeric/exceptions.rb
67
+ - lib/hexdump/numeric/hexadecimal.rb
68
+ - lib/hexdump/numeric/octal.rb
69
+ - lib/hexdump/reader.rb
70
+ - lib/hexdump/theme.rb
71
+ - lib/hexdump/theme/ansi.rb
72
+ - lib/hexdump/theme/rule.rb
73
+ - lib/hexdump/type.rb
74
+ - lib/hexdump/types.rb
59
75
  - lib/hexdump/version.rb
76
+ - spec/chars_spec.rb
60
77
  - spec/core_ext_spec.rb
61
- - spec/dumper_spec.rb
62
- - spec/hexdump_spec.rb
78
+ - spec/hexdump_class_spec.rb
79
+ - spec/hexdump_module_spec.rb
80
+ - spec/mixin_spec.rb
81
+ - spec/numeric/binary_spec.rb
82
+ - spec/numeric/char_or_int_spec.rb
83
+ - spec/numeric/decimal_spec.rb
84
+ - spec/numeric/hexadecimal_spec.rb
85
+ - spec/numeric/octal_spec.rb
86
+ - spec/reader_spec.rb
63
87
  - spec/spec_helper.rb
88
+ - spec/theme/ansi_spec.rb
89
+ - spec/theme/rule_spec.rb
90
+ - spec/theme_spec.rb
91
+ - spec/type_spec.rb
92
+ - spec/types_spec.rb
64
93
  homepage: https://github.com/postmodern/hexdump.rb#readme
65
94
  licenses:
66
95
  - MIT
@@ -69,7 +98,7 @@ metadata:
69
98
  source_code_uri: https://github.com/postmodern/hexdump.rb
70
99
  bug_tracker_uri: https://github.com/postmodern/hexdump.rb/issues
71
100
  changelog_uri: https://github.com/postmodern/hexdump.rb/blob/master/ChangeLog.md
72
- post_install_message:
101
+ post_install_message:
73
102
  rdoc_options: []
74
103
  require_paths:
75
104
  - lib
@@ -84,8 +113,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
84
113
  - !ruby/object:Gem::Version
85
114
  version: '0'
86
115
  requirements: []
87
- rubygems_version: 3.1.6
88
- signing_key:
116
+ rubygems_version: 3.2.22
117
+ signing_key:
89
118
  specification_version: 4
90
119
  summary: Hexdump Strings and IO objects.
91
120
  test_files: []
data/.gemtest DELETED
File without changes
@@ -1,419 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Hexdump
4
- #
5
- # Handles the parsing of data and formatting of the hexdump.
6
- #
7
- # @since 0.2.0
8
- #
9
- class Dumper
10
-
11
- # Widths for formatted numbers
12
- WIDTHS = {
13
- hexadecimal: ->(word_size) { word_size * 2 },
14
- decimal: {
15
- 1 => 3,
16
- 2 => 5,
17
- 4 => 10,
18
- 8 => 20
19
- },
20
- octal: {
21
- 1 => 3,
22
- 2 => 6,
23
- 4 => 11,
24
- 8 => 22
25
- },
26
- binary: ->(word_size) { word_size * 8 }
27
- }
28
-
29
- # Format Strings for the various bases
30
- FORMATS = {
31
- hexadecimal: ->(width) { "%.#{width}x" },
32
- decimal: ->(width) { "%#{width}.d" },
33
- octal: ->(width) { "%.#{width}o" },
34
- binary: ->(width) { "%.#{width}b" }
35
- }
36
-
37
- # Character to represent unprintable characters
38
- UNPRINTABLE = '.'
39
-
40
- # ASCII printable bytes and characters
41
- PRINTABLE = {
42
- 0x20 => " ",
43
- 0x21 => "!",
44
- 0x22 => "\"",
45
- 0x23 => "#",
46
- 0x24 => "$",
47
- 0x25 => "%",
48
- 0x26 => "&",
49
- 0x27 => "'",
50
- 0x28 => "(",
51
- 0x29 => ")",
52
- 0x2a => "*",
53
- 0x2b => "+",
54
- 0x2c => ",",
55
- 0x2d => "-",
56
- 0x2e => ".",
57
- 0x2f => "/",
58
- 0x30 => "0",
59
- 0x31 => "1",
60
- 0x32 => "2",
61
- 0x33 => "3",
62
- 0x34 => "4",
63
- 0x35 => "5",
64
- 0x36 => "6",
65
- 0x37 => "7",
66
- 0x38 => "8",
67
- 0x39 => "9",
68
- 0x3a => ":",
69
- 0x3b => ";",
70
- 0x3c => "<",
71
- 0x3d => "=",
72
- 0x3e => ">",
73
- 0x3f => "?",
74
- 0x40 => "@",
75
- 0x41 => "A",
76
- 0x42 => "B",
77
- 0x43 => "C",
78
- 0x44 => "D",
79
- 0x45 => "E",
80
- 0x46 => "F",
81
- 0x47 => "G",
82
- 0x48 => "H",
83
- 0x49 => "I",
84
- 0x4a => "J",
85
- 0x4b => "K",
86
- 0x4c => "L",
87
- 0x4d => "M",
88
- 0x4e => "N",
89
- 0x4f => "O",
90
- 0x50 => "P",
91
- 0x51 => "Q",
92
- 0x52 => "R",
93
- 0x53 => "S",
94
- 0x54 => "T",
95
- 0x55 => "U",
96
- 0x56 => "V",
97
- 0x57 => "W",
98
- 0x58 => "X",
99
- 0x59 => "Y",
100
- 0x5a => "Z",
101
- 0x5b => "[",
102
- 0x5c => "\\",
103
- 0x5d => "]",
104
- 0x5e => "^",
105
- 0x5f => "_",
106
- 0x60 => "`",
107
- 0x61 => "a",
108
- 0x62 => "b",
109
- 0x63 => "c",
110
- 0x64 => "d",
111
- 0x65 => "e",
112
- 0x66 => "f",
113
- 0x67 => "g",
114
- 0x68 => "h",
115
- 0x69 => "i",
116
- 0x6a => "j",
117
- 0x6b => "k",
118
- 0x6c => "l",
119
- 0x6d => "m",
120
- 0x6e => "n",
121
- 0x6f => "o",
122
- 0x70 => "p",
123
- 0x71 => "q",
124
- 0x72 => "r",
125
- 0x73 => "s",
126
- 0x74 => "t",
127
- 0x75 => "u",
128
- 0x76 => "v",
129
- 0x77 => "w",
130
- 0x78 => "x",
131
- 0x79 => "y",
132
- 0x7a => "z",
133
- 0x7b => "{",
134
- 0x7c => "|",
135
- 0x7d => "}",
136
- 0x7e => "~"
137
- }
138
-
139
- PRINTABLE.default = UNPRINTABLE
140
-
141
- # The base to dump words as.
142
- attr_reader :base
143
-
144
- # The size of the words parse from the data.
145
- attr_reader :word_size
146
-
147
- # The endianness of the words parsed from the data.
148
- attr_reader :endian
149
-
150
- # The width in words of each hexdump line.
151
- attr_reader :width
152
-
153
- # Whether to display ASCII characters alongside numeric values.
154
- attr_reader :ascii
155
-
156
- #
157
- # Creates a new Hexdump dumper.
158
- #
159
- # @param [Integer] width (16)
160
- # The number of bytes to dump for each line.
161
- #
162
- # @param [Integer] endian (:little)
163
- # The endianness that the bytes are organized in. Supported endianness
164
- # include `:little` and `:big`.
165
- #
166
- # @param [Integer] word_size (1)
167
- # The number of bytes within a word.
168
- #
169
- # @param [Symbol, Integer] base (:hexadecimal)
170
- # The base to print bytes in. Supported bases include, `:hexadecimal`,
171
- # `:hex`, `16, `:decimal`, `:dec`, `10, `:octal`, `:oct`, `8`,
172
- # `:binary`, `:bin` and `2`.
173
- #
174
- # @param [Boolean] ascii (false)
175
- # Print ascii characters when possible.
176
- #
177
- # @raise [ArgumentError]
178
- # The values for `:base` or `:endian` were unknown.
179
- #
180
- # @since 0.2.0
181
- #
182
- def initialize(width: 16,
183
- endian: :little,
184
- word_size: 1,
185
- base: :hexadecimal,
186
- ascii: false)
187
-
188
- @base = case base
189
- when :hexadecimal, :hex, 16 then :hexadecimal
190
- when :decimal, :dec, 10 then :decimal
191
- when :octal, :oct, 8 then :octal
192
- when :binary, :bin, 2 then :binary
193
- when nil then :hexadecimal
194
- else
195
- raise(ArgumentError,"unknown base #{base.inspect}")
196
- end
197
-
198
- @word_size = word_size
199
- @endian = case endian
200
- when 'little', :little then :little
201
- when 'big', :big then :big
202
- when nil then :little
203
- else
204
- raise(ArgumentError,"unknown endian: #{endian.inspect}")
205
- end
206
-
207
- @width = (width / @word_size)
208
- @ascii = ascii
209
-
210
- @format_width = (WIDTHS[@base][@word_size] || 1)
211
- @format = FORMATS[@base][@format_width]
212
-
213
- if @word_size == 1
214
- @format_cache = Hash.new do |hash,key|
215
- hash[key] = sprintf(@format,key)
216
- end
217
- end
218
- end
219
-
220
- #
221
- # Iterates over every word within the data.
222
- #
223
- # @param [#each_byte] data
224
- # The data containing bytes.
225
- #
226
- # @yield [word]
227
- # The given block will be passed each word within the data.
228
- #
229
- # @yieldparam [Integer]
230
- # An unpacked word from the data.
231
- #
232
- # @return [Enumerator]
233
- # If no block is given, an Enumerator will be returned.
234
- #
235
- # @raise [ArgumentError]
236
- # The given data does not define the `#each_byte` method.
237
- #
238
- # @since 0.2.0
239
- #
240
- def each_word(data,&block)
241
- return enum_for(:each_word,data) unless block
242
-
243
- unless data.respond_to?(:each_byte)
244
- raise(ArgumentError,"the data to hexdump must define #each_byte")
245
- end
246
-
247
- if @word_size > 1
248
- word = 0
249
- count = 0
250
-
251
- init_shift = if @endian == :big then ((@word_size - 1) * 8)
252
- else 0
253
- end
254
- shift = init_shift
255
-
256
- data.each_byte do |b|
257
- word |= (b << shift)
258
-
259
- if @endian == :big then shift -= 8
260
- else shift += 8
261
- end
262
-
263
- count += 1
264
-
265
- if count >= @word_size
266
- yield word
267
-
268
- word = 0
269
- count = 0
270
- shift = init_shift
271
- end
272
- end
273
-
274
- # yield the remaining word
275
- yield word if count > 0
276
- else
277
- data.each_byte(&block)
278
- end
279
- end
280
-
281
- #
282
- # Iterates over the hexdump.
283
- #
284
- # @param [#each_byte] data
285
- # The data to be hexdumped.
286
- #
287
- # @yield [index,numeric,printable]
288
- # The given block will be passed the hexdump break-down of each
289
- # segment.
290
- #
291
- # @yieldparam [Integer] index
292
- # The index of the hexdumped segment.
293
- #
294
- # @yieldparam [Array<String>] numeric
295
- # The numeric representation of the segment.
296
- #
297
- # @yieldparam [Array<String>] printable
298
- # The printable representation of the segment.
299
- #
300
- # @return [Integer, Enumerator]
301
- # If a block is given, then the final number of bytes read is returned.
302
- # If no block is given, an Enumerator will be returned.
303
- #
304
- # @since 0.2.0
305
- #
306
- def each(data)
307
- return enum_for(:each,data) unless block_given?
308
-
309
- index = 0
310
- count = 0
311
-
312
- numeric = Array.new(@width)
313
- printable = Array.new(@width)
314
-
315
- each_word(data) do |word|
316
- numeric[count] = format_numeric(word)
317
- printable[count] = format_printable(word)
318
-
319
- count += 1
320
-
321
- if count >= @width
322
- yield index, numeric, printable
323
-
324
- index += (@width * @word_size)
325
- count = 0
326
- end
327
- end
328
-
329
- if count > 0
330
- # yield the remaining data
331
- yield index, numeric[0,count], printable[0,count]
332
-
333
- index += (count * @word_size)
334
- end
335
-
336
- return index
337
- end
338
-
339
- #
340
- # Dumps the hexdump.
341
- #
342
- # @param [#each_byte] data
343
- # The data to be hexdumped.
344
- #
345
- # @param [#<<] output
346
- # The output to dump the hexdump to.
347
- #
348
- # @return [nil]
349
- #
350
- # @raise [ArgumentError]
351
- # The output value does not support the `#<<` method.
352
- #
353
- # @since 0.2.0
354
- #
355
- def dump(data,output=$stdout)
356
- unless output.respond_to?(:<<)
357
- raise(ArgumentError,"output must support the #<< method")
358
- end
359
-
360
- bytes_segment_width = ((@width * @format_width) + @width)
361
- index_format = "%.8x"
362
- line_format = "#{index_format} %-#{bytes_segment_width}s |%s|#{$/}"
363
-
364
- length = each(data) do |index,numeric,printable|
365
- output << sprintf(line_format,index,numeric.join(' '),printable.join)
366
- end
367
-
368
- output << sprintf("#{index_format}#{$/}",length)
369
- return nil
370
- end
371
-
372
- #
373
- # Converts the word into a numeric String.
374
- #
375
- # @param [Integer] word
376
- # The word to convert.
377
- #
378
- # @return [String]
379
- # The numeric representation of the word.
380
- #
381
- # @since 0.2.0
382
- #
383
- def format_numeric(word)
384
- if @word_size == 1
385
- if (@ascii && (word >= 0x20 && word <= 0x7e))
386
- PRINTABLE[word]
387
- else
388
- @format_cache[word]
389
- end
390
- else
391
- sprintf(@format,word)
392
- end
393
- end
394
-
395
- #
396
- # Converts a word into a printable String.
397
- #
398
- # @param [Integer] word
399
- # The word to convert.
400
- #
401
- # @return [String]
402
- # The printable representation of the word.
403
- #
404
- # @since 0.2.0
405
- #
406
- def format_printable(word)
407
- if @word_size == 1
408
- PRINTABLE[word]
409
- elsif word >= 0 && word <= 0x7fffffff
410
- # XXX: https://github.com/jruby/jruby/issues/6652
411
- char = word.chr(Encoding::UTF_8) rescue nil
412
- char || UNPRINTABLE
413
- else
414
- UNPRINTABLE
415
- end
416
- end
417
-
418
- end
419
- end