hexdump 0.3.0 → 1.0.0

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.
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