bit-struct 0.15.0 → 0.16
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/History.txt +5 -1
- data/LICENSE +56 -0
- data/README.md +2 -2
- data/Rakefile +2 -2
- data/examples/field-ripper.rb +1 -1
- data/examples/ip.rb +6 -6
- data/examples/longlong.rb +2 -2
- data/examples/md.rb +1 -1
- data/examples/modular-def.rb +2 -2
- data/examples/native.rb +3 -3
- data/examples/ping.rb +1 -1
- data/examples/raw.rb +1 -1
- data/examples/switch-endian.rb +2 -2
- data/examples/vector.rb +2 -2
- data/lib/bit-struct.rb +0 -11
- data/lib/bit-struct/bit-struct.rb +54 -144
- data/lib/bit-struct/char-field.rb +3 -3
- data/lib/bit-struct/field.rb +94 -0
- data/lib/bit-struct/fields.rb +13 -13
- data/lib/bit-struct/float-field.rb +4 -4
- data/lib/bit-struct/hex-octet-field.rb +3 -3
- data/lib/bit-struct/nested-field.rb +8 -8
- data/lib/bit-struct/octet-field.rb +4 -4
- data/lib/bit-struct/signed-field.rb +23 -28
- data/lib/bit-struct/text-field.rb +2 -2
- data/lib/bit-struct/unsigned-field.rb +24 -27
- data/lib/bit-struct/vector-field.rb +7 -7
- data/lib/bit-struct/vector.rb +21 -21
- data/lib/bit-struct/yaml.rb +2 -2
- data/test/test-endian.rb +3 -3
- data/test/test-vector.rb +4 -4
- data/test/test.rb +49 -43
- metadata +47 -45
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8b4260733d87afeaad67a83a5e81bce6f5445885
|
4
|
+
data.tar.gz: 6d271698553f2cff7d062f9c095c9e395fbd7233
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 76fd8928a0eeb632b70e8b81c3a2ded19649659e9ede7473dd7ebbc3257ea1eb14ed8cbcc2150606f997394be8774eeee37870ae772388f5795af59bdc94d57f
|
7
|
+
data.tar.gz: 670298e1efc0da14c23efc1fedb00c27c6bf2f3488a85f6a70234b45ca7c3858961449def4840aca9fdb71aeeb70d99d00dcc6cdd9217e68229ccc48e9e23ae6
|
data/History.txt
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
+
bit-struct 0.16
|
2
|
+
|
3
|
+
- updated for ruby 2.4
|
4
|
+
|
1
5
|
bit-struct 0.15
|
2
6
|
|
3
7
|
- modernize rakefile and gemspec
|
@@ -35,7 +39,7 @@ bit-struct 0.10
|
|
35
39
|
- Fixed a bug when calling #to_yaml on a BitStruct with a pad field. Thanks
|
36
40
|
to Jay Reitz for reporting it and providing the solution.
|
37
41
|
|
38
|
-
- Added BitStruct.default_options. Particularly useful for default endian
|
42
|
+
- Added BitStruct.default_options. Particularly useful for default endian
|
39
43
|
settings--see examples/native.rb.
|
40
44
|
|
41
45
|
- Fixed a bug that prevented warning about field name conflicts with
|
data/LICENSE
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
bit-struct is copyrighted free software by Joel VanderWerf <vjoel@users.sourceforge.net>
|
2
|
+
You can redistribute it and/or modify it under either the terms of the
|
3
|
+
2-clause BSDL (see the file BSDL), or the conditions below:
|
4
|
+
|
5
|
+
1. You may make and give away verbatim copies of the source form of the
|
6
|
+
software without restriction, provided that you duplicate all of the
|
7
|
+
original copyright notices and associated disclaimers.
|
8
|
+
|
9
|
+
2. You may modify your copy of the software in any way, provided that
|
10
|
+
you do at least ONE of the following:
|
11
|
+
|
12
|
+
a) place your modifications in the Public Domain or otherwise
|
13
|
+
make them Freely Available, such as by posting said
|
14
|
+
modifications to Usenet or an equivalent medium, or by allowing
|
15
|
+
the author to include your modifications in the software.
|
16
|
+
|
17
|
+
b) use the modified software only within your corporation or
|
18
|
+
organization.
|
19
|
+
|
20
|
+
c) give non-standard binaries non-standard names, with
|
21
|
+
instructions on where to get the original software distribution.
|
22
|
+
|
23
|
+
d) make other distribution arrangements with the author.
|
24
|
+
|
25
|
+
3. You may distribute the software in object code or binary form,
|
26
|
+
provided that you do at least ONE of the following:
|
27
|
+
|
28
|
+
a) distribute the binaries and library files of the software,
|
29
|
+
together with instructions (in the manual page or equivalent)
|
30
|
+
on where to get the original distribution.
|
31
|
+
|
32
|
+
b) accompany the distribution with the machine-readable source of
|
33
|
+
the software.
|
34
|
+
|
35
|
+
c) give non-standard binaries non-standard names, with
|
36
|
+
instructions on where to get the original software distribution.
|
37
|
+
|
38
|
+
d) make other distribution arrangements with the author.
|
39
|
+
|
40
|
+
4. You may modify and include the part of the software into any other
|
41
|
+
software (possibly commercial). But some files in the distribution
|
42
|
+
are not written by the author, so that they are not under these terms.
|
43
|
+
|
44
|
+
For the list of those files and their copying conditions, see the
|
45
|
+
file LEGAL.
|
46
|
+
|
47
|
+
5. The scripts and library files supplied as input to or produced as
|
48
|
+
output from the software do not automatically fall under the
|
49
|
+
copyright of the software, but belong to whomever generated them,
|
50
|
+
and may be sold commercially, and may be aggregated with this
|
51
|
+
software.
|
52
|
+
|
53
|
+
6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
|
54
|
+
IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
55
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
56
|
+
PURPOSE.
|
data/README.md
CHANGED
@@ -82,7 +82,7 @@ BitStruct is most efficient when your data is primarily treated as a binary stri
|
|
82
82
|
* Fields that are not aligned on byte boundaries may cross no more than two bytes boundaries. (See examples/byte-bdy.rb.)
|
83
83
|
|
84
84
|
* No variable length fields (except the #rest field).
|
85
|
-
|
85
|
+
|
86
86
|
## Future plans ##
|
87
87
|
|
88
88
|
* Currently, the library is written in pure ruby. The implementation uses Array#pack and String#unpack calls, as well as shifting and masking in pure ruby. Future versions will optionally generate a customized C extension for better efficiency.
|
@@ -186,4 +186,4 @@ This software is distributed under the Ruby license. See http://www.ruby-lang.or
|
|
186
186
|
## Author ##
|
187
187
|
|
188
188
|
Joel VanderWerf, mailto:vjoel@users.sourceforge.net
|
189
|
-
Copyright (c) 2005-
|
189
|
+
Copyright (c) 2005-2014, Joel VanderWerf.
|
data/Rakefile
CHANGED
@@ -25,7 +25,7 @@ end
|
|
25
25
|
desc "Commit, tag, and push repo; build and push gem"
|
26
26
|
task :release => "release:is_new_version" do
|
27
27
|
require 'tempfile'
|
28
|
-
|
28
|
+
|
29
29
|
sh "gem build #{PRJ}.gemspec"
|
30
30
|
|
31
31
|
file = Tempfile.new "template"
|
@@ -41,7 +41,7 @@ task :release => "release:is_new_version" do
|
|
41
41
|
sh "git tag #{tag}"
|
42
42
|
sh "git push"
|
43
43
|
sh "git push --tags"
|
44
|
-
|
44
|
+
|
45
45
|
sh "gem push #{tag}.gem"
|
46
46
|
end
|
47
47
|
|
data/examples/field-ripper.rb
CHANGED
data/examples/ip.rb
CHANGED
@@ -15,7 +15,7 @@ class IP < BitStruct
|
|
15
15
|
rest :body, "Body of message"
|
16
16
|
|
17
17
|
note " rest is application defined message body"
|
18
|
-
|
18
|
+
|
19
19
|
initial_value.ip_v = 4
|
20
20
|
initial_value.ip_hl = 5
|
21
21
|
end
|
@@ -33,7 +33,7 @@ if __FILE__ == $0
|
|
33
33
|
ip1.ip_dst = "192.168.1.255"
|
34
34
|
ip1.body = "This is the payload text."
|
35
35
|
ip1.ip_len = ip1.length
|
36
|
-
|
36
|
+
|
37
37
|
ip2 = IP.new do |ip|
|
38
38
|
ip.ip_tos = 0
|
39
39
|
ip.ip_len = 0
|
@@ -47,7 +47,7 @@ if __FILE__ == $0
|
|
47
47
|
ip.body = "This is the payload text."
|
48
48
|
ip.ip_len = ip.length
|
49
49
|
end
|
50
|
-
|
50
|
+
|
51
51
|
ip3 = IP.new(
|
52
52
|
:ip_tos => 0,
|
53
53
|
:ip_len => 0,
|
@@ -62,15 +62,15 @@ if __FILE__ == $0
|
|
62
62
|
) do |ip|
|
63
63
|
ip.ip_len = ip.length
|
64
64
|
end
|
65
|
-
|
65
|
+
|
66
66
|
ip4 = IP.new(ip1) # Construct from a BitStruct (or String)
|
67
|
-
|
67
|
+
|
68
68
|
raise unless ip1 == ip2
|
69
69
|
raise unless ip1 == ip3
|
70
70
|
raise unless ip1 == ip4
|
71
71
|
|
72
72
|
ip = ip1
|
73
|
-
|
73
|
+
|
74
74
|
puts ip.inspect
|
75
75
|
puts "-"*50
|
76
76
|
puts ip.inspect_detailed
|
data/examples/longlong.rb
CHANGED
@@ -10,8 +10,8 @@ pkt = MyPacket.new
|
|
10
10
|
pkt.x = 59843759843759843
|
11
11
|
pkt.y = 59843759843759843
|
12
12
|
|
13
|
-
p pkt.x # 59843759843759843
|
14
|
-
p pkt.y # 59843759843759843
|
13
|
+
p pkt.x # 59843759843759843
|
14
|
+
p pkt.y # 59843759843759843
|
15
15
|
|
16
16
|
p pkt
|
17
17
|
# #<MyPacket x=59843759843759843, y=59843759843759843>
|
data/examples/md.rb
CHANGED
data/examples/modular-def.rb
CHANGED
@@ -6,7 +6,7 @@ module ModuleMethodSaver
|
|
6
6
|
@saved ||= []
|
7
7
|
@saved << [meth, args, block]
|
8
8
|
end
|
9
|
-
|
9
|
+
|
10
10
|
def included(m)
|
11
11
|
if @saved
|
12
12
|
@saved.each do |meth, args, block|
|
@@ -21,7 +21,7 @@ require 'bit-struct'
|
|
21
21
|
|
22
22
|
module M
|
23
23
|
extend ModuleMethodSaver
|
24
|
-
|
24
|
+
|
25
25
|
unsigned :x, 13
|
26
26
|
signed :y, 7
|
27
27
|
end
|
data/examples/native.rb
CHANGED
@@ -6,15 +6,15 @@ class NativeNumbers < BitStruct
|
|
6
6
|
unsigned :x1, 13, :endian => :native
|
7
7
|
unsigned :x2, 2, :endian => :native
|
8
8
|
unsigned :x3, 32, :endian => :native
|
9
|
-
|
9
|
+
|
10
10
|
float :f1, 32, :endian => :native
|
11
11
|
float :f2, 64, :endian => :native
|
12
12
|
float :f3, 32
|
13
13
|
float :f4, 64
|
14
|
-
|
14
|
+
|
15
15
|
default_options :endian => :native
|
16
16
|
# affects fields defined after this and in subclasses
|
17
|
-
|
17
|
+
|
18
18
|
unsigned :y1, 32
|
19
19
|
|
20
20
|
end
|
data/examples/ping.rb
CHANGED
data/examples/raw.rb
CHANGED
data/examples/switch-endian.rb
CHANGED
@@ -3,7 +3,7 @@ module ModuleMethodSaver
|
|
3
3
|
@saved ||= []
|
4
4
|
@saved << [meth, args, block]
|
5
5
|
end
|
6
|
-
|
6
|
+
|
7
7
|
def included(m)
|
8
8
|
if @saved
|
9
9
|
@saved.each do |meth, args, block|
|
@@ -18,7 +18,7 @@ require 'bit-struct'
|
|
18
18
|
|
19
19
|
module MyFields
|
20
20
|
extend ModuleMethodSaver
|
21
|
-
|
21
|
+
|
22
22
|
unsigned :x, 16
|
23
23
|
end
|
24
24
|
|
data/examples/vector.rb
CHANGED
@@ -5,7 +5,7 @@ class Vec < BitStruct::Vector
|
|
5
5
|
# these declarations apply to *each* entry in the vector:
|
6
6
|
unsigned :x, 16
|
7
7
|
signed :y, 32
|
8
|
-
|
8
|
+
|
9
9
|
Entry = struct_class # Give it a name, just for inspect to look nice
|
10
10
|
end
|
11
11
|
|
@@ -72,7 +72,7 @@ puts
|
|
72
72
|
# Example 4: vector field in a bitstruct
|
73
73
|
class Packet < BitStruct
|
74
74
|
unsigned :stuff, 32, "whatever"
|
75
|
-
|
75
|
+
|
76
76
|
# Using the Vec class defined above
|
77
77
|
vector :v, Vec, "a vector", 5
|
78
78
|
|
data/lib/bit-struct.rb
CHANGED
@@ -1,14 +1,3 @@
|
|
1
|
-
# A Convenience to load all field classes and yaml handling.
|
2
|
-
|
3
|
-
if "a"[0].kind_of? Fixnum
|
4
|
-
unless Fixnum.methods.include? :ord
|
5
|
-
class Fixnum
|
6
|
-
def ord; self; end
|
7
|
-
end
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
11
1
|
require 'bit-struct/bit-struct'
|
12
2
|
require 'bit-struct/fields'
|
13
3
|
require 'bit-struct/yaml'
|
14
|
-
|
@@ -9,100 +9,11 @@
|
|
9
9
|
# The String#replace method is useful.
|
10
10
|
#
|
11
11
|
class BitStruct < String
|
12
|
-
VERSION = "0.
|
13
|
-
|
14
|
-
class Field
|
15
|
-
# Offset of field in bits.
|
16
|
-
attr_reader :offset
|
17
|
-
|
18
|
-
# Length of field in bits.
|
19
|
-
attr_reader :length
|
20
|
-
alias size length
|
21
|
-
|
22
|
-
# Name of field (used for its accessors).
|
23
|
-
attr_reader :name
|
24
|
-
|
25
|
-
# Options, such as :default (varies for each field subclass).
|
26
|
-
# In general, options can be provided as strings or as symbols.
|
27
|
-
attr_reader :options
|
28
|
-
|
29
|
-
# Display name of field (used for printing).
|
30
|
-
attr_reader :display_name
|
31
|
-
|
32
|
-
# Default value.
|
33
|
-
attr_reader :default
|
34
|
-
|
35
|
-
# Format for printed value of field.
|
36
|
-
attr_reader :format
|
37
|
-
|
38
|
-
# Subclasses can override this to define a default for all fields of this
|
39
|
-
# class, not just the one currently being added to a BitStruct class, a
|
40
|
-
# "default default" if you will. The global default, if #default returns
|
41
|
-
# nil, is to fill the field with zero. Most field classes just let this
|
42
|
-
# default stand. The default can be overridden per-field when a BitStruct
|
43
|
-
# class is defined.
|
44
|
-
def self.default; nil; end
|
45
|
-
|
46
|
-
# Used in describe.
|
47
|
-
def self.class_name
|
48
|
-
@class_name ||= name[/\w+$/]
|
49
|
-
end
|
50
|
-
|
51
|
-
# Used in describe. Can be overridden per-subclass, as in NestedField.
|
52
|
-
def class_name
|
53
|
-
self.class.class_name
|
54
|
-
end
|
55
|
-
|
56
|
-
# Yield the description of this field, as an array of 5 strings: byte
|
57
|
-
# offset, type, name, size, and description. The opts hash may have:
|
58
|
-
#
|
59
|
-
# :expand :: if the value is true, expand complex fields
|
60
|
-
#
|
61
|
-
# (Subclass implementations may yield more than once for complex fields.)
|
62
|
-
#
|
63
|
-
def describe opts
|
64
|
-
bits = size
|
65
|
-
if bits > 32 and bits % 8 == 0
|
66
|
-
len_str = "%dB" % (bits/8)
|
67
|
-
else
|
68
|
-
len_str = "%db" % bits
|
69
|
-
end
|
70
|
-
|
71
|
-
byte_offset = offset / 8 + (opts[:byte_offset] || 0)
|
12
|
+
VERSION = "0.16"
|
72
13
|
|
73
|
-
|
74
|
-
end
|
75
|
-
|
76
|
-
# Options are _display_name_, _default_, and _format_ (subclasses of Field
|
77
|
-
# may add other options).
|
78
|
-
def initialize(offset, length, name, opts = {})
|
79
|
-
@offset, @length, @name, @options =
|
80
|
-
offset, length, name, opts
|
81
|
-
|
82
|
-
@display_name = opts[:display_name] || opts["display_name"]
|
83
|
-
@default = opts[:default] || opts["default"] || self.class.default
|
84
|
-
@format = opts[:format] || opts["format"]
|
85
|
-
end
|
86
|
-
|
87
|
-
# Inspect the value of this field in the specified _obj_.
|
88
|
-
def inspect_in_object(obj, opts)
|
89
|
-
val = obj.send(name)
|
90
|
-
str =
|
91
|
-
begin
|
92
|
-
val.inspect_with_options(opts)
|
93
|
-
rescue NoMethodError
|
94
|
-
val.inspect
|
95
|
-
end
|
96
|
-
(f=@format) ? (f % str) : str
|
97
|
-
end
|
98
|
-
|
99
|
-
# Normally, all fields show up in inspect, but some, such as padding,
|
100
|
-
# should not.
|
101
|
-
def inspectable?; true; end
|
102
|
-
end
|
103
|
-
|
14
|
+
require 'bit-struct/field'
|
104
15
|
NULL_FIELD = Field.new(0, 0, :null, :display_name => "null field")
|
105
|
-
|
16
|
+
|
106
17
|
# Raised when a field is added after an instance has been created. Fields
|
107
18
|
# cannot be added after this point.
|
108
19
|
class ClosedClassError < StandardError; end
|
@@ -110,9 +21,9 @@ class BitStruct < String
|
|
110
21
|
# Raised if the chosen field name is not allowed, either because another
|
111
22
|
# field by that name exists, or because a method by that name exists.
|
112
23
|
class FieldNameError < StandardError; end
|
113
|
-
|
24
|
+
|
114
25
|
@default_options = {}
|
115
|
-
|
26
|
+
|
116
27
|
@initial_value = nil
|
117
28
|
@closed = nil
|
118
29
|
@rest_field = nil
|
@@ -127,7 +38,7 @@ class BitStruct < String
|
|
127
38
|
@note = nil
|
128
39
|
end
|
129
40
|
end
|
130
|
-
|
41
|
+
|
131
42
|
# ------------------------
|
132
43
|
# :section: field access methods
|
133
44
|
#
|
@@ -139,7 +50,7 @@ class BitStruct < String
|
|
139
50
|
def fields
|
140
51
|
@fields ||= self == BitStruct ? [] : superclass.fields.dup
|
141
52
|
end
|
142
|
-
|
53
|
+
|
143
54
|
# Return the list of fields defined by this class, not inherited
|
144
55
|
# from the superclass.
|
145
56
|
def own_fields
|
@@ -150,9 +61,9 @@ class BitStruct < String
|
|
150
61
|
def add_field(name, length, opts = {})
|
151
62
|
round_byte_length ## just to make sure this has been calculated
|
152
63
|
## before adding anything
|
153
|
-
|
64
|
+
|
154
65
|
name = name.to_sym
|
155
|
-
|
66
|
+
|
156
67
|
if @closed
|
157
68
|
raise ClosedClassError, "Cannot add field #{name}: " +
|
158
69
|
"The definition of the #{self.inspect} BitStruct class is closed."
|
@@ -169,9 +80,9 @@ class BitStruct < String
|
|
169
80
|
raise FieldNameError,"Field #{name} is already defined as a method."
|
170
81
|
end
|
171
82
|
end
|
172
|
-
|
83
|
+
|
173
84
|
field_class = opts[:field_class]
|
174
|
-
|
85
|
+
|
175
86
|
prev = fields[-1] || NULL_FIELD
|
176
87
|
offset = prev.offset + prev.length
|
177
88
|
field = field_class.new(offset, length, name, opts)
|
@@ -194,13 +105,13 @@ class BitStruct < String
|
|
194
105
|
def parse_options(ary, default_name, default_field_class) # :nodoc:
|
195
106
|
opts = ary.grep(Hash).first || {}
|
196
107
|
opts = default_options.merge(opts)
|
197
|
-
|
108
|
+
|
198
109
|
opts[:display_name] = ary.grep(String).first || default_name
|
199
110
|
opts[:field_class] = ary.grep(Class).first || default_field_class
|
200
|
-
|
111
|
+
|
201
112
|
opts
|
202
113
|
end
|
203
|
-
|
114
|
+
|
204
115
|
# Get or set the hash of default options for the class, which apply to all
|
205
116
|
# fields. Changes take effect immediately, so can be used alternatingly with
|
206
117
|
# blocks of field declarations. If +h+ is provided, update the default
|
@@ -214,17 +125,17 @@ class BitStruct < String
|
|
214
125
|
end
|
215
126
|
@default_options
|
216
127
|
end
|
217
|
-
|
128
|
+
|
218
129
|
# Length, in bits, of this object.
|
219
130
|
def bit_length
|
220
131
|
@bit_length ||= fields.inject(0) {|a, f| a + f.length}
|
221
132
|
end
|
222
|
-
|
133
|
+
|
223
134
|
# Length, in bytes (rounded up), of this object.
|
224
135
|
def round_byte_length
|
225
136
|
@round_byte_length ||= (bit_length/8.0).ceil
|
226
137
|
end
|
227
|
-
|
138
|
+
|
228
139
|
def closed! # :nodoc:
|
229
140
|
@closed = true
|
230
141
|
end
|
@@ -239,17 +150,17 @@ class BitStruct < String
|
|
239
150
|
field
|
240
151
|
end
|
241
152
|
end
|
242
|
-
|
153
|
+
|
243
154
|
# Return the list of fields for this class.
|
244
155
|
def fields
|
245
156
|
self.class.fields
|
246
157
|
end
|
247
|
-
|
158
|
+
|
248
159
|
# Return the rest field for this class.
|
249
160
|
def rest_field
|
250
161
|
self.class.rest_field
|
251
162
|
end
|
252
|
-
|
163
|
+
|
253
164
|
# Return the field with the given name.
|
254
165
|
def field_by_name name
|
255
166
|
self.class.field_by_name name
|
@@ -266,7 +177,7 @@ class BitStruct < String
|
|
266
177
|
# Default format for describe. Fields are byte, type, name, size,
|
267
178
|
# and description.
|
268
179
|
DESCRIBE_FORMAT = "%8s: %-12s %-14s[%4s] %s"
|
269
|
-
|
180
|
+
|
270
181
|
# Can be overridden to use a different format.
|
271
182
|
def describe_format
|
272
183
|
DESCRIBE_FORMAT
|
@@ -279,7 +190,7 @@ class BitStruct < String
|
|
279
190
|
if fmt.kind_of? Hash
|
280
191
|
opts = fmt; fmt = nil
|
281
192
|
end
|
282
|
-
|
193
|
+
|
283
194
|
if block_given?
|
284
195
|
fields.each do |field|
|
285
196
|
field.describe(opts) do |desc|
|
@@ -287,7 +198,7 @@ class BitStruct < String
|
|
287
198
|
end
|
288
199
|
end
|
289
200
|
nil
|
290
|
-
|
201
|
+
|
291
202
|
else
|
292
203
|
fmt ||= describe_format
|
293
204
|
|
@@ -311,7 +222,7 @@ class BitStruct < String
|
|
311
222
|
result
|
312
223
|
end
|
313
224
|
end
|
314
|
-
|
225
|
+
|
315
226
|
# Subclasses can use this to append a string (or several) to the #describe
|
316
227
|
# output. Notes are not cumulative with inheritance. When used with no
|
317
228
|
# arguments simply returns the note string
|
@@ -320,7 +231,7 @@ class BitStruct < String
|
|
320
231
|
@note
|
321
232
|
end
|
322
233
|
end
|
323
|
-
|
234
|
+
|
324
235
|
# ------------------------
|
325
236
|
# :section: initialization and conversion methods
|
326
237
|
#
|
@@ -339,9 +250,9 @@ class BitStruct < String
|
|
339
250
|
value.each do |k, v|
|
340
251
|
send "#{k}=", v
|
341
252
|
end
|
342
|
-
|
253
|
+
|
343
254
|
when nil
|
344
|
-
|
255
|
+
|
345
256
|
else
|
346
257
|
if value.respond_to?(:read)
|
347
258
|
value = value.read(self.class.round_byte_length)
|
@@ -349,16 +260,16 @@ class BitStruct < String
|
|
349
260
|
|
350
261
|
self[0, value.length] = value
|
351
262
|
end
|
352
|
-
|
263
|
+
|
353
264
|
self.class.closed!
|
354
265
|
yield self if block_given?
|
355
266
|
end
|
356
|
-
|
267
|
+
|
357
268
|
DEFAULT_TO_H_OPTS = {
|
358
269
|
:convert_keys => :to_sym,
|
359
270
|
:include_rest => true
|
360
271
|
}
|
361
|
-
|
272
|
+
|
362
273
|
# Returns a hash of {name=>value,...} for each field. By default, include
|
363
274
|
# the rest field.
|
364
275
|
# Keys are symbols derived from field names using +to_sym+, unless
|
@@ -370,13 +281,13 @@ class BitStruct < String
|
|
370
281
|
if opts[:include_rest] and (rest_field = self.class.rest_field)
|
371
282
|
fields_for_to_h += [rest_field]
|
372
283
|
end
|
373
|
-
|
284
|
+
|
374
285
|
fields_for_to_h.inject({}) do |h,f|
|
375
286
|
h[f.name.send(converter)] = send(f.name)
|
376
287
|
h
|
377
288
|
end
|
378
289
|
end
|
379
|
-
|
290
|
+
|
380
291
|
# Returns an array of values of the fields of the BitStruct. By default,
|
381
292
|
# include the rest field.
|
382
293
|
def to_a(include_rest = true)
|
@@ -384,17 +295,16 @@ class BitStruct < String
|
|
384
295
|
fields.map do |f|
|
385
296
|
send(f.name)
|
386
297
|
end
|
387
|
-
|
298
|
+
|
388
299
|
if include_rest and (rest_field = self.class.rest_field)
|
389
300
|
ary << send(rest_field.name)
|
390
301
|
end
|
391
302
|
ary
|
392
303
|
end
|
393
|
-
|
394
|
-
## temporary hack for 1.9
|
304
|
+
|
395
305
|
if "a"[0].kind_of? String
|
396
306
|
def [](*args)
|
397
|
-
if args.size == 1 and args[0].kind_of?(
|
307
|
+
if args.size == 1 and args[0].kind_of?(Integer)
|
398
308
|
super.ord
|
399
309
|
else
|
400
310
|
super
|
@@ -402,14 +312,14 @@ class BitStruct < String
|
|
402
312
|
end
|
403
313
|
|
404
314
|
def []=(*args)
|
405
|
-
if args.size == 2 and (i=args[0]).kind_of?(
|
315
|
+
if args.size == 2 and (i=args[0]).kind_of?(Integer)
|
406
316
|
super(i, args[1].chr)
|
407
317
|
else
|
408
318
|
super
|
409
319
|
end
|
410
320
|
end
|
411
321
|
end
|
412
|
-
|
322
|
+
|
413
323
|
class << self
|
414
324
|
# The unique "prototype" object from which new instances are copied.
|
415
325
|
# The fields of this instance can be modified in the class definition
|
@@ -423,7 +333,7 @@ class BitStruct < String
|
|
423
333
|
#
|
424
334
|
def initial_value # :yields: the initial value
|
425
335
|
unless @initial_value
|
426
|
-
iv = defined?(superclass.initial_value) ?
|
336
|
+
iv = defined?(superclass.initial_value) ?
|
427
337
|
superclass.initial_value.dup : ""
|
428
338
|
if iv.length < round_byte_length
|
429
339
|
iv << "\0" * (round_byte_length - iv.length)
|
@@ -432,7 +342,7 @@ class BitStruct < String
|
|
432
342
|
@initial_value = "" # Serves as initval while the real initval is inited
|
433
343
|
@initial_value = new(iv)
|
434
344
|
@closed = false # only creating the first _real_ instance closes.
|
435
|
-
|
345
|
+
|
436
346
|
fields.each do |field|
|
437
347
|
@initial_value.send("#{field.name}=", field.default) if field.default
|
438
348
|
end
|
@@ -440,7 +350,7 @@ class BitStruct < String
|
|
440
350
|
yield @initial_value if block_given?
|
441
351
|
@initial_value
|
442
352
|
end
|
443
|
-
|
353
|
+
|
444
354
|
# Take +data+ (a string or BitStruct) and parse it into instances of
|
445
355
|
# the +classes+, returning them in an array. The classes can be given
|
446
356
|
# as an array or a separate arguments. (For parsing a string into a _single_
|
@@ -450,7 +360,7 @@ class BitStruct < String
|
|
450
360
|
c.new(data.slice!(0...c.round_byte_length))
|
451
361
|
end
|
452
362
|
end
|
453
|
-
|
363
|
+
|
454
364
|
# Join the given structs (array or multiple args) as a string.
|
455
365
|
# Actually, the inherited String#+ instance method is the same, as is using
|
456
366
|
# Array#join.
|
@@ -474,7 +384,7 @@ class BitStruct < String
|
|
474
384
|
:include_class => true,
|
475
385
|
:simple_format => "<%s>"
|
476
386
|
}
|
477
|
-
|
387
|
+
|
478
388
|
DETAILED_INSPECT_OPTS = {
|
479
389
|
:format => "%s:\n%s",
|
480
390
|
:field_format => "%30s = %s",
|
@@ -485,34 +395,34 @@ class BitStruct < String
|
|
485
395
|
:include_class => true,
|
486
396
|
:simple_format => "\n%s"
|
487
397
|
}
|
488
|
-
|
398
|
+
|
489
399
|
# A standard inspect method which does not add newlines.
|
490
400
|
def inspect_with_options(opts = DEFAULT_INSPECT_OPTS)
|
491
401
|
field_format = opts[:field_format]
|
492
402
|
field_name_meth = opts[:field_name_meth]
|
493
|
-
|
403
|
+
|
494
404
|
fields_for_inspect = fields.select {|field| field.inspectable?}
|
495
405
|
if opts[:include_rest] and (rest_field = self.class.rest_field)
|
496
406
|
fields_for_inspect << rest_field
|
497
407
|
end
|
498
|
-
|
408
|
+
|
499
409
|
ary = fields_for_inspect.map do |field|
|
500
410
|
field_format %
|
501
411
|
[field.send(field_name_meth),
|
502
412
|
field.inspect_in_object(self, opts)]
|
503
413
|
end
|
504
|
-
|
414
|
+
|
505
415
|
body = ary.join(opts[:separator])
|
506
|
-
|
416
|
+
|
507
417
|
if opts[:include_class]
|
508
418
|
opts[:format] % [self.class, body]
|
509
419
|
else
|
510
420
|
opts[:simple_format] % body
|
511
421
|
end
|
512
422
|
end
|
513
|
-
|
423
|
+
|
514
424
|
alias inspect inspect_with_options
|
515
|
-
|
425
|
+
|
516
426
|
# A more visually appealing inspect method that puts each field/value on
|
517
427
|
# a separate line. Very useful when output is scrolling by on a screen.
|
518
428
|
#
|
@@ -526,7 +436,7 @@ class BitStruct < String
|
|
526
436
|
# :section: field declaration methods
|
527
437
|
#
|
528
438
|
# ------------------------
|
529
|
-
|
439
|
+
|
530
440
|
# Define accessors for a variable length substring from the end of
|
531
441
|
# the defined fields to the end of the BitStruct. The _rest_ may behave as
|
532
442
|
# a String or as some other String or BitStruct subclass.
|
@@ -544,13 +454,13 @@ class BitStruct < String
|
|
544
454
|
# If a hash is provided, use it for options.
|
545
455
|
#
|
546
456
|
# *Warning*: the rest reader method returns a copy of the field, so
|
547
|
-
# accessors on that returned value do not affect the original rest field.
|
457
|
+
# accessors on that returned value do not affect the original rest field.
|
548
458
|
#
|
549
459
|
def self.rest(name, *ary)
|
550
460
|
if @rest_field
|
551
461
|
raise ArgumentError, "Duplicate rest field: #{name.inspect}."
|
552
462
|
end
|
553
|
-
|
463
|
+
|
554
464
|
opts = parse_options(ary, name, String)
|
555
465
|
offset = round_byte_length
|
556
466
|
byte_range = offset..-1
|
@@ -563,14 +473,14 @@ class BitStruct < String
|
|
563
473
|
define_method "#{name}=" do |val|
|
564
474
|
self[byte_range] = val
|
565
475
|
end
|
566
|
-
|
476
|
+
|
567
477
|
@rest_field = Field.new(offset, -1, name, {
|
568
478
|
:display_name => opts[:display_name],
|
569
479
|
:rest_class => field_class
|
570
480
|
})
|
571
481
|
end
|
572
482
|
end
|
573
|
-
|
483
|
+
|
574
484
|
# Not included with the other fields, but accessible separately.
|
575
485
|
def self.rest_field; @rest_field; end
|
576
486
|
end
|