bit-struct 0.15.0 → 0.16
Sign up to get free protection for your applications and to get access to all the features.
- 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
|