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.
- checksums.yaml +4 -4
- data/ChangeLog.md +68 -2
- data/Gemfile +1 -0
- data/README.md +486 -135
- data/benchmark.rb +29 -22
- data/lib/hexdump/chars.rb +46 -0
- data/lib/hexdump/core_ext/file.rb +68 -6
- data/lib/hexdump/core_ext/io.rb +2 -2
- data/lib/hexdump/core_ext/kernel.rb +7 -0
- data/lib/hexdump/core_ext/string.rb +2 -2
- data/lib/hexdump/core_ext/string_io.rb +2 -2
- data/lib/hexdump/core_ext.rb +1 -0
- data/lib/hexdump/format_string.rb +43 -0
- data/lib/hexdump/hexdump.rb +768 -75
- data/lib/hexdump/mixin.rb +198 -0
- data/lib/hexdump/module_methods.rb +132 -0
- data/lib/hexdump/numeric/binary.rb +55 -0
- data/lib/hexdump/numeric/char_or_int.rb +90 -0
- data/lib/hexdump/numeric/decimal.rb +56 -0
- data/lib/hexdump/numeric/exceptions.rb +11 -0
- data/lib/hexdump/numeric/hexadecimal.rb +59 -0
- data/lib/hexdump/numeric/octal.rb +55 -0
- data/lib/hexdump/numeric.rb +5 -0
- data/lib/hexdump/reader.rb +314 -0
- data/lib/hexdump/theme/ansi.rb +81 -0
- data/lib/hexdump/theme/rule.rb +159 -0
- data/lib/hexdump/theme.rb +61 -0
- data/lib/hexdump/type.rb +232 -0
- data/lib/hexdump/types.rb +108 -0
- data/lib/hexdump/version.rb +1 -1
- data/lib/hexdump.rb +12 -1
- data/spec/chars_spec.rb +76 -0
- data/spec/core_ext_spec.rb +10 -6
- data/spec/hexdump_class_spec.rb +1708 -0
- data/spec/hexdump_module_spec.rb +23 -0
- data/spec/mixin_spec.rb +37 -0
- data/spec/numeric/binary_spec.rb +239 -0
- data/spec/numeric/char_or_int_spec.rb +210 -0
- data/spec/numeric/decimal_spec.rb +317 -0
- data/spec/numeric/hexadecimal_spec.rb +320 -0
- data/spec/numeric/octal_spec.rb +239 -0
- data/spec/reader_spec.rb +863 -0
- data/spec/theme/ansi_spec.rb +242 -0
- data/spec/theme/rule_spec.rb +199 -0
- data/spec/theme_spec.rb +94 -0
- data/spec/type_spec.rb +317 -0
- data/spec/types_spec.rb +904 -0
- metadata +39 -10
- data/.gemtest +0 -0
- data/lib/hexdump/dumper.rb +0 -419
- data/spec/dumper_spec.rb +0 -329
- data/spec/hexdump_spec.rb +0 -30
@@ -0,0 +1,198 @@
|
|
1
|
+
require 'hexdump/hexdump'
|
2
|
+
|
3
|
+
module Hexdump
|
4
|
+
#
|
5
|
+
# Provides a {hexdump Mixin#hexdump} method that can be included into objects.
|
6
|
+
#
|
7
|
+
# class DataObject
|
8
|
+
#
|
9
|
+
# include Hexdump::Mixin
|
10
|
+
#
|
11
|
+
# def each_byte
|
12
|
+
# # ...
|
13
|
+
# end
|
14
|
+
#
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
# data.hexdump
|
18
|
+
#
|
19
|
+
# @api public
|
20
|
+
#
|
21
|
+
# @since 1.0.0
|
22
|
+
#
|
23
|
+
module Mixin
|
24
|
+
#
|
25
|
+
# Prints a hexdumps of the object.
|
26
|
+
#
|
27
|
+
# @param [#print] output ($stdout)
|
28
|
+
# The output to print the hexdump to.
|
29
|
+
#
|
30
|
+
# @param [Integer] offset
|
31
|
+
# The offset to start the index at.
|
32
|
+
#
|
33
|
+
# @param [Hash{Symbol => Object}] kwargs
|
34
|
+
# Additional keyword arguments for {Hexdump#initialize}.
|
35
|
+
#
|
36
|
+
# @option kwargs [:int8, :uint8, :char, :uchar, :byte, :int16, :int16_le, :int16_be, :int16_ne, :uint16, :uint16_le, :uint16_be, :uint16_ne, :short, :short_le, :short_be, :short_ne, :ushort, :ushort_le, :ushort_be, :ushort_ne, :int32, :int32_le, :int32_be, :int32_ne, :uint32, :uint32_le, :uint32_be, :uint32_ne, :int, :long, :long_le, :long_be, :long_ne, :uint, :ulong, :ulong_le, :ulong_be, :ulong_ne, :int64, :int64_le, :int64_be, :int64_ne, :uint64, :uint64_le, :uint64_be, :uint64_ne, :long_long, :long_long_le, :long_long_be, :long_long_ne, :ulong_long, :ulong_long_le, :ulong_long_be, :ulong_long_ne, :float, :float_le, :float_be, :float_ne, :double, :double_le, :double_be, :double_ne] :type (:byte)
|
37
|
+
# The type to decode the data as.
|
38
|
+
#
|
39
|
+
# @option kwargs [Integer, nil] :offset
|
40
|
+
# Controls whether to skip N number of bytes before starting to read data.
|
41
|
+
#
|
42
|
+
# @option kwargs [Integer, nil] :length
|
43
|
+
# Controls control many bytes to read.
|
44
|
+
#
|
45
|
+
# @option kwargs [Boolean] :zero_pad (false)
|
46
|
+
# Enables or disables zero padding of data, so that the remaining bytes
|
47
|
+
# can be decoded as a uint, int, or float.
|
48
|
+
#
|
49
|
+
# @option kwargs [Integer] :columns (16)
|
50
|
+
# The number of bytes to dump for each line.
|
51
|
+
#
|
52
|
+
# @option kwargs [Integer, nil] :group_columns
|
53
|
+
# Separate groups of columns with an additional space.
|
54
|
+
#
|
55
|
+
# @option kwargs [Integer, :type, nil] :group_chars
|
56
|
+
# Group chars into columns.
|
57
|
+
# If `:type`, then the chars will be grouped by the `type`'s size.
|
58
|
+
#
|
59
|
+
# @option kwargs [Boolean] :repeating
|
60
|
+
# Controls whether to omit repeating duplicate rows data with a `*`.
|
61
|
+
#
|
62
|
+
# @option kwargs [16, 10, 8, 2] :base (16)
|
63
|
+
# The base to print bytes in.
|
64
|
+
#
|
65
|
+
# @option kwargs [16, 10, 8, 2] :index_base (16)
|
66
|
+
# Control the base that the index is displayed in.
|
67
|
+
#
|
68
|
+
# @option kwargs [Boolean] :chars_column (true)
|
69
|
+
# Controls whether to display the characters column.
|
70
|
+
#
|
71
|
+
# @option kwargs [:ascii, :utf8, Encoding, nil] :encoding
|
72
|
+
# The encoding to display the characters in.
|
73
|
+
#
|
74
|
+
# @option kwargs [Integer, nil] :index_offset
|
75
|
+
# The offset to start the index at.
|
76
|
+
#
|
77
|
+
# @option kwargs [Boolean, Hash{:index,:numeric,:chars => Symbol,Array<Symbol>}] :style
|
78
|
+
# Enables theming of index, numeric, or chars columns.
|
79
|
+
#
|
80
|
+
# @option kwargs [Boolean, Hash{:index,:numeric,:chars => Hash{String,Regexp => Symbol,Array<Symbol>}}] :highlights
|
81
|
+
# Enables selective highlighting of index, numeric, or chars columns.
|
82
|
+
#
|
83
|
+
# @yield [hexdump]
|
84
|
+
# If a block is given, it will be passed the newly initialized hexdump
|
85
|
+
# instance.
|
86
|
+
#
|
87
|
+
# @yieldparam [Hexdump::Hexdump] hexdump
|
88
|
+
# The newly initialized hexdump instance.
|
89
|
+
#
|
90
|
+
# @raise [ArgumentError]
|
91
|
+
# The given data does not define the `#each_byte` method,
|
92
|
+
# the `:output` value does not support the `#<<` method or
|
93
|
+
# the `:base` value was unknown.
|
94
|
+
#
|
95
|
+
# @example
|
96
|
+
# obj.hexdump
|
97
|
+
# # ...
|
98
|
+
#
|
99
|
+
# @example Hexdumping to a custom output:
|
100
|
+
# File.open('hexdump.txt') do |output|
|
101
|
+
# obj.hexdump(output: output)
|
102
|
+
# end
|
103
|
+
#
|
104
|
+
# @example Hexdumping to an Array:
|
105
|
+
# lines = []
|
106
|
+
# obj.hexdump(output: lines)
|
107
|
+
#
|
108
|
+
def hexdump(output: $stdout, **kwargs,&block)
|
109
|
+
hexdump = ::Hexdump::Hexdump.new(**kwargs,&block)
|
110
|
+
|
111
|
+
hexdump.hexdump(self, output: output)
|
112
|
+
end
|
113
|
+
|
114
|
+
#
|
115
|
+
# Outputs the hexdump to a String.
|
116
|
+
#
|
117
|
+
# @param [Integer] offset
|
118
|
+
# The offset to start the index at.
|
119
|
+
#
|
120
|
+
# @param [Hash{Symbol => Object}] kwargs
|
121
|
+
# Additional keyword arguments for {Hexdump#initialize}.
|
122
|
+
#
|
123
|
+
# @option kwargs [:int8, :uint8, :char, :uchar, :byte, :int16, :int16_le, :int16_be, :int16_ne, :uint16, :uint16_le, :uint16_be, :uint16_ne, :short, :short_le, :short_be, :short_ne, :ushort, :ushort_le, :ushort_be, :ushort_ne, :int32, :int32_le, :int32_be, :int32_ne, :uint32, :uint32_le, :uint32_be, :uint32_ne, :int, :long, :long_le, :long_be, :long_ne, :uint, :ulong, :ulong_le, :ulong_be, :ulong_ne, :int64, :int64_le, :int64_be, :int64_ne, :uint64, :uint64_le, :uint64_be, :uint64_ne, :long_long, :long_long_le, :long_long_be, :long_long_ne, :ulong_long, :ulong_long_le, :ulong_long_be, :ulong_long_ne, :float, :float_le, :float_be, :float_ne, :double, :double_le, :double_be, :double_ne] :type (:byte)
|
124
|
+
# The type to decode the data as.
|
125
|
+
#
|
126
|
+
# @option kwargs [Integer, nil] :offset
|
127
|
+
# Controls whether to skip N number of bytes before starting to read data.
|
128
|
+
#
|
129
|
+
# @option kwargs [Integer, nil] :length
|
130
|
+
# Controls control many bytes to read.
|
131
|
+
#
|
132
|
+
# @option kwargs [Boolean] :zero_pad (false)
|
133
|
+
# Enables or disables zero padding of data, so that the remaining bytes
|
134
|
+
# can be decoded as a uint, int, or float.
|
135
|
+
#
|
136
|
+
# @option kwargs [Integer] :columns (16)
|
137
|
+
# The number of bytes to dump for each line.
|
138
|
+
#
|
139
|
+
# @option kwargs [Integer, nil] :group_columns
|
140
|
+
# Separate groups of columns with an additional space.
|
141
|
+
#
|
142
|
+
# @option kwargs [Integer, :type, nil] :group_chars
|
143
|
+
# Group chars into columns.
|
144
|
+
# If `:type`, then the chars will be grouped by the `type`'s size.
|
145
|
+
#
|
146
|
+
# @option kwargs [Boolean] :repeating
|
147
|
+
# Controls whether to omit repeating duplicate rows data with a `*`.
|
148
|
+
#
|
149
|
+
# @option kwargs [16, 10, 8, 2] :base (16)
|
150
|
+
# The base to print bytes in.
|
151
|
+
#
|
152
|
+
# @option kwargs [16, 10, 8, 2] :index_base (16)
|
153
|
+
# Control the base that the index is displayed in.
|
154
|
+
#
|
155
|
+
# @option kwargs [Integer, nil] :index_offset
|
156
|
+
# The offset to start the index at.
|
157
|
+
#
|
158
|
+
# @option kwargs [Boolean] :chars_column (true)
|
159
|
+
# Controls whether to display the characters column.
|
160
|
+
#
|
161
|
+
# @option kwargs [:ascii, :utf8, Encoding, nil] :encoding
|
162
|
+
# The encoding to display the characters in.
|
163
|
+
#
|
164
|
+
# @option kwargs [Boolean, Hash{:index,:numeric,:chars => Symbol,Array<Symbol>}] :style
|
165
|
+
# Enables theming of index, numeric, or chars columns.
|
166
|
+
#
|
167
|
+
# @option kwargs [Boolean, Hash{:index,:numeric,:chars => Hash{String,Regexp => Symbol,Array<Symbol>}}] :highlights
|
168
|
+
# Enables selective highlighting of index, numeric, or chars columns.
|
169
|
+
#
|
170
|
+
# @yield [hexdump]
|
171
|
+
# If a block is given, it will be passed the newly initialized hexdump
|
172
|
+
# instance.
|
173
|
+
#
|
174
|
+
# @yieldparam [Hexdump::Hexdump] hexdump
|
175
|
+
# The newly initialized hexdump instance.
|
176
|
+
#
|
177
|
+
# @return [String]
|
178
|
+
# The output of the hexdump.
|
179
|
+
#
|
180
|
+
# @raise [ArgumentError]
|
181
|
+
# The given data does not define the `#each_byte` method,
|
182
|
+
# the `:base` value was unknown.
|
183
|
+
#
|
184
|
+
# @note
|
185
|
+
# **Caution:** this method appends each line of the hexdump to a String,
|
186
|
+
# and that String can grow quite large and consume a lot of memory.
|
187
|
+
#
|
188
|
+
# @example
|
189
|
+
# obj.hexdump
|
190
|
+
# # => "..."
|
191
|
+
#
|
192
|
+
def to_hexdump(**kwargs,&block)
|
193
|
+
hexdump = ::Hexdump::Hexdump.new(**kwargs,&block)
|
194
|
+
|
195
|
+
hexdump.dump(self)
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
@@ -0,0 +1,132 @@
|
|
1
|
+
require 'hexdump/hexdump'
|
2
|
+
|
3
|
+
module Hexdump
|
4
|
+
#
|
5
|
+
# Provides the {hexdump ModuleMethods#hexdump} top-level method that can be
|
6
|
+
# extended into modules.
|
7
|
+
#
|
8
|
+
# module Context
|
9
|
+
#
|
10
|
+
# extend Hexdump::ModuleMethods
|
11
|
+
#
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
module ModuleMethods
|
15
|
+
#
|
16
|
+
# Hexdumps the given data.
|
17
|
+
#
|
18
|
+
# @param [#each_byte] data
|
19
|
+
# The data to be hexdumped.
|
20
|
+
#
|
21
|
+
# @param [#print] output ($stdout)
|
22
|
+
# The output to print the hexdump to.
|
23
|
+
#
|
24
|
+
# @param [Hash{Symbol => Object}] kwargs
|
25
|
+
# Additional keyword arguments for {Hexdump#initialize}.
|
26
|
+
#
|
27
|
+
# @option kwargs [:int8, :uint8, :char, :uchar, :byte, :int16, :int16_le, :int16_be, :int16_ne, :uint16, :uint16_le, :uint16_be, :uint16_ne, :short, :short_le, :short_be, :short_ne, :ushort, :ushort_le, :ushort_be, :ushort_ne, :int32, :int32_le, :int32_be, :int32_ne, :uint32, :uint32_le, :uint32_be, :uint32_ne, :int, :long, :long_le, :long_be, :long_ne, :uint, :ulong, :ulong_le, :ulong_be, :ulong_ne, :int64, :int64_le, :int64_be, :int64_ne, :uint64, :uint64_le, :uint64_be, :uint64_ne, :long_long, :long_long_le, :long_long_be, :long_long_ne, :ulong_long, :ulong_long_le, :ulong_long_be, :ulong_long_ne, :float, :float_le, :float_be, :float_ne, :double, :double_le, :double_be, :double_ne] :type (:byte)
|
28
|
+
# The type to decode the data as.
|
29
|
+
#
|
30
|
+
# @option kwargs [Integer, nil] :offset
|
31
|
+
# Controls whether to skip N number of bytes before starting to read data.
|
32
|
+
#
|
33
|
+
# @option kwargs [Integer, nil] :length
|
34
|
+
# Controls control many bytes to read.
|
35
|
+
#
|
36
|
+
# @option kwargs [Boolean] :zero_pad (false)
|
37
|
+
# Enables or disables zero padding of data, so that the remaining bytes
|
38
|
+
# can be decoded as a uint, int, or float.
|
39
|
+
#
|
40
|
+
# @option kwargs [Integer] :columns (16)
|
41
|
+
# The number of bytes to dump for each line.
|
42
|
+
#
|
43
|
+
# @option kwargs [Integer, nil] :group_columns
|
44
|
+
# Separate groups of columns with an additional space.
|
45
|
+
#
|
46
|
+
# @option kwargs [Integer, :type, nil] :group_chars
|
47
|
+
# Group chars into columns.
|
48
|
+
# If `:type`, then the chars will be grouped by the `type`'s size.
|
49
|
+
#
|
50
|
+
# @option kwargs [Boolean] :repeating
|
51
|
+
# Controls whether to omit repeating duplicate rows data with a `*`.
|
52
|
+
#
|
53
|
+
# @option kwargs [16, 10, 8, 2] :base (16)
|
54
|
+
# The base to print bytes in.
|
55
|
+
#
|
56
|
+
# @option kwargs [16, 10, 8, 2] :index_base (16)
|
57
|
+
# Control the base that the index is displayed in.
|
58
|
+
#
|
59
|
+
# @option kwargs [Integer, nil] :index_offset
|
60
|
+
# The offset to start the index at.
|
61
|
+
#
|
62
|
+
# @option kwargs [Boolean] :chars_column (true)
|
63
|
+
# Controls whether to display the characters column.
|
64
|
+
#
|
65
|
+
# @option kwargs [:ascii, :utf8, Encoding, nil] :encoding
|
66
|
+
# The encoding to display the characters in.
|
67
|
+
#
|
68
|
+
# @option kwargs [Boolean, Hash{:index,:numeric,:chars => Symbol,Array<Symbol>}] :style
|
69
|
+
# Enables theming of index, numeric, or chars columns.
|
70
|
+
#
|
71
|
+
# @option kwargs [Boolean, Hash{:index,:numeric,:chars => Hash{String,Regexp => Symbol,Array<Symbol>}}] :highlights
|
72
|
+
# Enables selective highlighting of index, numeric, or chars columns.
|
73
|
+
#
|
74
|
+
# @yield [hexdump]
|
75
|
+
# If a block is given, it will be passed the newly initialized hexdump
|
76
|
+
# instance.
|
77
|
+
#
|
78
|
+
# @yieldparam [Hexdump::Hexdump] hexdump
|
79
|
+
# The newly initialized hexdump instance.
|
80
|
+
#
|
81
|
+
# @raise [ArgumentError]
|
82
|
+
# The given data does not define the `#each_byte` method,
|
83
|
+
# the `:output` value does not support the `#<<` method or
|
84
|
+
# the `:base` value was unknown.
|
85
|
+
#
|
86
|
+
# @example
|
87
|
+
# hexdump("hello\0")
|
88
|
+
# # 00000000 68 65 6c 6c 6f 00 |hello.|
|
89
|
+
# # 00000006
|
90
|
+
#
|
91
|
+
# @example Hexdumping to a custom output:
|
92
|
+
# File.open('hexdump.txt') do |output|
|
93
|
+
# hexdump("hello\0", output: output)
|
94
|
+
# end
|
95
|
+
#
|
96
|
+
# @example Hexdumping to an Array:
|
97
|
+
# lines = []
|
98
|
+
# hexdump("hello\0", output: lines)
|
99
|
+
#
|
100
|
+
# @example Hexdumping with ANSI styling:
|
101
|
+
# Hexdump.hexdump(style: {index: :white, numeric: :green, chars: :cyan})
|
102
|
+
#
|
103
|
+
# @example Hexdumping with ANSI highlighting:
|
104
|
+
# Hexdump.hexdump("hello\0", highlights: {
|
105
|
+
# index: {/00$/ => [:white, :bold]},
|
106
|
+
# numeric: {
|
107
|
+
# /^[8-f][0-9a-f]$/ => :faint,
|
108
|
+
# /f/ => :cyan,
|
109
|
+
# '00' => [:black, :on_red]
|
110
|
+
# },
|
111
|
+
# chars: {/[^\.]+/ => :green}
|
112
|
+
# })
|
113
|
+
#
|
114
|
+
# @example Configuring the hexdump with a block:
|
115
|
+
# Hexdump.hexdump("hello\0") do |hexdump|
|
116
|
+
# hexdump.type = :uint16
|
117
|
+
# # ...
|
118
|
+
#
|
119
|
+
# hexdump.theme do |theme|
|
120
|
+
# theme.index.highlight(/00$/, [:white, :bold])
|
121
|
+
# theme.numeric.highlight(/^[8-f][0-9a-f]$/, :faint)
|
122
|
+
# # ...
|
123
|
+
# end
|
124
|
+
# end
|
125
|
+
#
|
126
|
+
def hexdump(data, output: $stdout, **kwargs,&block)
|
127
|
+
hexdump = ::Hexdump::Hexdump.new(**kwargs,&block)
|
128
|
+
|
129
|
+
hexdump.hexdump(data, output: output)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'hexdump/numeric/exceptions'
|
2
|
+
require 'hexdump/format_string'
|
3
|
+
|
4
|
+
module Hexdump
|
5
|
+
module Numeric
|
6
|
+
#
|
7
|
+
# @api private
|
8
|
+
#
|
9
|
+
# @since 1.0.0
|
10
|
+
#
|
11
|
+
class Binary < FormatString
|
12
|
+
|
13
|
+
SIZE_TO_WIDTH = {
|
14
|
+
1 => 8, # 0xff.to_s(2).length
|
15
|
+
2 => 16, # 0xffff.to_s(2).length
|
16
|
+
4 => 32, # 0xffffffff.to_s(2).length
|
17
|
+
8 => 64 # 0xffffffffffffffff.to_s(2).length
|
18
|
+
}
|
19
|
+
|
20
|
+
# @return [Integer]
|
21
|
+
attr_reader :width
|
22
|
+
|
23
|
+
#
|
24
|
+
# Initializes the binary format.
|
25
|
+
#
|
26
|
+
# @param [Type::Int, Type::UInt] type
|
27
|
+
#
|
28
|
+
# @raise [NotImplementedError]
|
29
|
+
#
|
30
|
+
# @raise [IncompatibleTypeError]
|
31
|
+
#
|
32
|
+
# @raise [TypeError]
|
33
|
+
#
|
34
|
+
def initialize(type)
|
35
|
+
case type
|
36
|
+
when Type::Int, Type::UInt
|
37
|
+
@width = SIZE_TO_WIDTH.fetch(type.size) do
|
38
|
+
raise(NotImplementedError,"type #{type} with unsupported size #{type.size}")
|
39
|
+
end
|
40
|
+
|
41
|
+
if type.signed?
|
42
|
+
super("% .#{@width}b"); @width += 1
|
43
|
+
else
|
44
|
+
super("%.#{@width}b")
|
45
|
+
end
|
46
|
+
when Type::Float
|
47
|
+
raise(IncompatibleTypeError,"cannot format floating-point numbers in binary")
|
48
|
+
else
|
49
|
+
raise(TypeError,"unsupported type: #{type.inspect}")
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'hexdump/format_string'
|
2
|
+
|
3
|
+
module Hexdump
|
4
|
+
module Numeric
|
5
|
+
#
|
6
|
+
# @api private
|
7
|
+
#
|
8
|
+
# @since 1.0.0
|
9
|
+
#
|
10
|
+
class CharOrInt < FormatString
|
11
|
+
|
12
|
+
# @return [Base::Hexadecimal, Base::Decimal, Base::Octal, Base::Binary]
|
13
|
+
attr_reader :base
|
14
|
+
|
15
|
+
# @return [Encoding, nil]
|
16
|
+
attr_reader :encoding
|
17
|
+
|
18
|
+
#
|
19
|
+
# Initializes the character format.
|
20
|
+
#
|
21
|
+
# @param [Base::Hexadecimal, Base::Decimal, Base::Octal, Base::Binary] base
|
22
|
+
# The numeric base format to fallback to if a value does not map to a
|
23
|
+
# character.
|
24
|
+
#
|
25
|
+
# @param [Encoding, nil] encoding
|
26
|
+
# The optional encoding to convert bytes to.
|
27
|
+
#
|
28
|
+
def initialize(base,encoding=nil)
|
29
|
+
@base = base
|
30
|
+
@encoding = encoding
|
31
|
+
|
32
|
+
super("%#{@base.width}s")
|
33
|
+
end
|
34
|
+
|
35
|
+
def width
|
36
|
+
@base.width
|
37
|
+
end
|
38
|
+
|
39
|
+
#
|
40
|
+
# Formats a given ASCII byte value to a character or numeric format.
|
41
|
+
#
|
42
|
+
# @param [Integer] value
|
43
|
+
# The ASCII byte value.
|
44
|
+
#
|
45
|
+
# @return [String]
|
46
|
+
# The character or numeric formatted value.
|
47
|
+
#
|
48
|
+
def %(value)
|
49
|
+
if value == 0x00
|
50
|
+
super("\\0")
|
51
|
+
elsif value == 0x07
|
52
|
+
super("\\a")
|
53
|
+
elsif value == 0x08
|
54
|
+
super("\\b")
|
55
|
+
elsif value == 0x09
|
56
|
+
super("\\t")
|
57
|
+
elsif value == 0x0a
|
58
|
+
super("\\n")
|
59
|
+
elsif value == 0x0b
|
60
|
+
super("\\v")
|
61
|
+
elsif value == 0x0c
|
62
|
+
super("\\f")
|
63
|
+
elsif value == 0x0d
|
64
|
+
super("\\r")
|
65
|
+
else
|
66
|
+
if @encoding
|
67
|
+
if value >= 0x00
|
68
|
+
char = value.chr(@encoding) rescue nil
|
69
|
+
|
70
|
+
if char && char =~ /[[:print:]]/
|
71
|
+
super(char)
|
72
|
+
else
|
73
|
+
@base % value
|
74
|
+
end
|
75
|
+
else
|
76
|
+
@base % value
|
77
|
+
end
|
78
|
+
else
|
79
|
+
if (value >= 0x20 && value <= 0x7e)
|
80
|
+
super(value.chr)
|
81
|
+
else
|
82
|
+
@base % value
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|