bitstream 0.0.2 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.en CHANGED
@@ -65,6 +65,10 @@ gzip-viewer.rb: A viewer of the original file name of a gzip file.
65
65
  puts "The gzip does not contain its original file name."
66
66
  end
67
67
 
68
+ == Documentation
69
+
70
+ In preparation.
71
+
68
72
  == License
69
73
 
70
74
  This library is distributed under the dual license of the Ruby license (in the narrow sense) and the 2-clause BSD license. Please see http://www.ruby-lang.org and BSDL.
data/lib/bitstream.rb CHANGED
@@ -1,22 +1,31 @@
1
1
  # Author:: Natsuki Kawai (natsuki.kawai@gmail.com)
2
- # Copyright:: Copyright 2011 Natsuki Kawai
2
+ # Copyright:: Copyright (c) 2011, 2012 Natsuki Kawai
3
3
  # License:: 2-clause BSDL or Ruby's
4
4
 
5
5
  require 'random-accessible'
6
+ require 'lazy-string'
6
7
 
7
8
  require 'types/integer'
8
9
  require 'types/string'
9
10
  require 'types/cstring'
10
11
  require 'types/character'
11
12
 
13
+ require 'bitstream/utils'
14
+
12
15
  module BitStream
13
16
 
14
17
  class BitStreamError < Exception
15
18
  end
16
19
 
17
20
  Properties = Struct.new(
18
- :curr_offset, :fields, :mode, :raw_data,
19
- :initial_offset, :user_props, :eval_queue
21
+ :curr_offset,
22
+ :fields,
23
+ :mode,
24
+ :raw_data,
25
+ :initial_offset,
26
+ :user_props,
27
+ :eval_queue,
28
+ :substreams
20
29
  )
21
30
 
22
31
  class ArrayProxy
@@ -43,9 +52,6 @@ module BitStream
43
52
  def read_access(pos)
44
53
  unless @updated[pos]
45
54
  field = @fields[pos]
46
- unless field.has_read?
47
- BitStream.read_one_field(field, @instance)
48
- end
49
55
  @values[pos] = field.value
50
56
  @fields[pos] = nil
51
57
  @updated[pos] = true
@@ -78,6 +84,8 @@ module BitStream
78
84
 
79
85
  alias :enq :push
80
86
  alias :deq :shift
87
+ alias :peek_front :first
88
+ alias :peek_back :last
81
89
 
82
90
  end
83
91
 
@@ -104,59 +112,69 @@ module BitStream
104
112
  #end
105
113
  end
106
114
 
107
- module Utils
115
+ class SubStreamPacket
108
116
 
109
- def self.class2symbol(type)
110
- name = type.name.split("::").last
111
- name = self.camel2snake(name).intern
117
+ def self.instance(length)
118
+ new length
119
+ end
120
+
121
+ def initialize(length)
122
+ if length % 8 != 0
123
+ raise NotImplementedError, "non-aligned substream has not been supported."
124
+ end
125
+ @length = length
112
126
  end
113
127
 
114
- def self.camel2snake(camel)
115
- snake = camel.dup
116
- snake[0] = snake[0].downcase
117
- snake.gsub(/[A-Z]/) do |s|
118
- "_" + s.downcase
128
+ attr_reader :length
129
+
130
+ def read(s, offset)
131
+ if offset % 8 != 0
132
+ raise NotImplementedError, "non-aligned substream has not been supported."
119
133
  end
134
+ return [LazyString.new(s, offset / 8, @length / 8), @length]
120
135
  end
121
136
 
122
137
  end
123
138
 
124
- def self.read_one_field(value, instance)
125
- props = instance.bitstream_properties
126
- queue = props.eval_queue
139
+ class ReaderArray
127
140
 
128
- while value.offset.nil?
129
- field = queue.deq
130
- field.offset = props.curr_offset
131
- length = field.length
132
- length = field.decide_length if length.nil?
133
- props.curr_offset += length
141
+ def initialize
142
+ @array = []
143
+ @read = []
134
144
  end
135
- value.read
136
- end
137
-
138
- def self.index_all_fields(instance)
139
- props = instance.bitstream_properties
140
- queue = props.eval_queue
141
-
142
- queue.each do |field|
143
- field.offset = props.curr_offset
144
- length = field.length
145
- length = field.decide_length if length.nil?
146
- props.curr_offset += length
145
+
146
+ def [](pos)
147
+ unless @read[pos]
148
+ @read[pos] = true
149
+ reader = @array[pos]
150
+ if reader.value.nil?
151
+ reader.read
152
+ end
153
+ @array[pos] = reader.value
154
+ end
155
+ return @array[pos]
147
156
  end
148
- queue.clear
157
+
158
+ def <<(reader)
159
+ @array << reader
160
+ end
161
+
149
162
  end
150
-
151
- class Value
163
+
164
+ class FieldReader
152
165
 
153
- def initialize(type, raw_data)
166
+ def initialize(type, instance)
154
167
  @type = type
155
- @raw_data = raw_data
168
+ @instance = instance
156
169
  @length = @type.length if @type.respond_to? :length
157
170
  @has_read = false
158
171
  end
159
172
 
173
+ def props
174
+ @instance.bitstream_properties
175
+ end
176
+ private :props
177
+
160
178
  def has_read?
161
179
  @has_read
162
180
  end
@@ -164,29 +182,40 @@ module BitStream
164
182
  def read
165
183
  unless @has_read
166
184
  if @offset.nil?
167
- raise "Has not been set offset."
168
- else
169
- @value, @length = @type.read(@raw_data, @offset)
170
- @has_read = true
185
+ index
171
186
  end
187
+ @value, @length = @type.read(props.raw_data, @offset)
188
+ @has_read = true
172
189
  end
173
190
  return @value
174
191
  end
192
+
193
+ alias :value :read
175
194
 
176
- def decide_length
195
+ def length
177
196
  # @length must not be nil if @has_read.
178
197
  if @length.nil?
179
198
  if @offset.nil?
180
- raise "Has not been set offset."
199
+ index
181
200
  else
182
- @value, @length = @type.read(@raw_data, @offset)
201
+ @value, @length = @type.read(props.raw_data, @offset)
183
202
  @has_read = true
184
203
  end
185
204
  end
186
205
  return @length
187
206
  end
188
207
 
189
- attr_reader :length, :value
208
+ def index
209
+ queue = props.eval_queue
210
+
211
+ while @offset.nil?
212
+ field = queue.deq
213
+ field.offset = props.curr_offset
214
+ length = field.length
215
+ props.curr_offset += length
216
+ end
217
+ end
218
+
190
219
  attr_accessor :offset
191
220
 
192
221
  end
@@ -198,10 +227,33 @@ module BitStream
198
227
  @fields = {}
199
228
  @types = types.dup
200
229
  @index = 0
230
+ @singleton_props = {}
201
231
  @class_props = {}
232
+ @class_props_chain = [@class_props]
202
233
  @bitstream_mutex = Mutex.new
203
234
  end
204
235
 
236
+ # Currently BitStream does not support inheritance.
237
+ if false
238
+ def on_inherit(types, chain, fields, mutex)
239
+ @field_defs = []
240
+ @fields = fields
241
+ @types = types
242
+ @index = 0
243
+ @class_props = {}
244
+ @class_props_chain = [@class_props]
245
+ @class_props_chain.concat(chain)
246
+ @bitstream_mutex = mutex
247
+ end
248
+
249
+ def inherited(subclass)
250
+ subclass.on_inherit(@types, @class_props_chain, @fields, @bitstream_mutex)
251
+ def subclass.fields
252
+ raise NameError, "Cannot define fields on a subclass of a class includes BitStream."
253
+ end
254
+ end
255
+ end
256
+
205
257
  def fields(&field_def)
206
258
  @field_defs << field_def
207
259
  end
@@ -209,7 +261,14 @@ module BitStream
209
261
  def initialize_instance(raw_data, instance)
210
262
  props = instance.bitstream_properties
211
263
  props.mode = :field_def
212
- props.user_props.merge!(@class_props)
264
+
265
+ user_props = props.user_props
266
+
267
+ @class_props_chain.each do |class_props|
268
+ user_props.merge!(class_props)
269
+ end
270
+ user_props[:nest_chain] = user_props[:nest_chain] + [instance]
271
+
213
272
  @bitstream_mutex.synchronize do
214
273
  @instance = instance
215
274
 
@@ -217,9 +276,16 @@ module BitStream
217
276
  field_def.call
218
277
  end
219
278
  end
279
+ substream_types = @singleton_props[:substream_types]
280
+ substreams = props.substreams
281
+ unless substream_types.nil?
282
+ substreams.keys.each do |id|
283
+ # TODO: Support multi type substreams.
284
+ substreams[id] = substream_types[0].instance.read(substreams[id])
285
+ end
286
+ end
220
287
  end
221
288
 
222
-
223
289
  def self.types
224
290
  @types
225
291
  end
@@ -254,6 +320,10 @@ module BitStream
254
320
  @class_props[:byte_order] = order.intern
255
321
  end
256
322
 
323
+ def substream_types(*types)
324
+ @singleton_props[:substream_types] = types
325
+ end
326
+
257
327
  def self.add_type(type, name = nil, bs = self)
258
328
  bs.instance_eval do
259
329
  define_method(name) do |*args|
@@ -274,18 +344,13 @@ module BitStream
274
344
  else
275
345
  type_instance = type.instance(user_props, *args)
276
346
  end
277
- field = Value.new(type_instance, props.raw_data)
347
+ field = FieldReader.new(type_instance, @instance)
278
348
  queue.enq(field)
279
- @instance.bitstream_properties.fields[name] = field
280
349
 
281
350
  name_in_method = name
282
351
 
283
352
  @instance.singleton_class.instance_eval do
284
353
  define_method name do
285
- field = bitstream_properties.fields[name_in_method]
286
- if field.value.nil?
287
- BitStream.read_one_field(field, self)
288
- end
289
354
  field.value
290
355
  end
291
356
  end
@@ -325,10 +390,21 @@ module BitStream
325
390
  case props.mode
326
391
  when :field_def
327
392
  field = ArrayProxy.new(@instance)
328
- size.times do
329
- field_element = Value.new(type_instance, props.raw_data)
330
- field.add_field(field_element)
331
- queue.enq(field_element)
393
+ if size.respond_to?(:to_int) && size >= 0
394
+ size.times do
395
+ field_element = FieldReader.new(type_instance, @instance)
396
+ field.add_field(field_element)
397
+ queue.enq(field_element)
398
+ end
399
+ else
400
+ queue.peek_back.index unless queue.empty?
401
+ while props.curr_offset < props.raw_data.bytesize * 8
402
+ field_element = FieldReader.new(type_instance, @instance)
403
+ field.add_field(field_element)
404
+ queue.enq(field_element)
405
+ field_element.index
406
+ #puts "curr_offset:#{props.curr_offset} bytesize:#{props.raw_data.bytesize}"
407
+ end
332
408
  end
333
409
 
334
410
  @instance.singleton_class.instance_eval do
@@ -374,7 +450,7 @@ module BitStream
374
450
  if fields[name].nil?
375
451
  fields[name] = ArrayProxy.new(@instance)
376
452
  end
377
- field = Value.new(type_instance, props.raw_data)
453
+ field = FieldReader.new(type_instance, @instance)
378
454
  fields[name].add_field(field)
379
455
  queue.enq(field)
380
456
 
@@ -394,6 +470,34 @@ module BitStream
394
470
  end
395
471
  end
396
472
  end
473
+
474
+ def substream(name, id, length)
475
+ name = name.intern
476
+ props = @instance.bitstream_properties
477
+ user_props = props.user_props
478
+ raw_data = props.raw_data
479
+ queue = props.eval_queue
480
+ top_stream = @instance.bitstream_properties.user_props[:nest_chain].first
481
+ substreams = top_stream.bitstream_properties.substreams
482
+
483
+ case props.mode
484
+ when :field_def
485
+ type_instance = SubStreamPacket.instance(length)
486
+ field = FieldReader.new(type_instance, @instance)
487
+ queue.enq(field)
488
+ field.read
489
+
490
+ substreams[id] << LazyString.new if substreams[id].empty?
491
+ substreams[id].last << field.value
492
+ end
493
+ end
494
+
495
+ def separate_substream(id)
496
+ # TODO: Refactor here.
497
+ top_stream = @instance.bitstream_properties.user_props[:nest_chain].first
498
+ substreams = top_stream.bitstream_properties.substreams
499
+ substreams[id] << LazyString.new
500
+ end
397
501
 
398
502
  def add_type(type, name = nil)
399
503
  if name.nil?
@@ -412,17 +516,29 @@ module BitStream
412
516
  end
413
517
 
414
518
  def create_with_offset(s, offset, props = {})
519
+ props[:nest_chain] = [] unless props.include?(:nest_chain)
415
520
  klass = Class.new(self)
416
- instance = klass.new(s, offset)
521
+ instance = klass.new
522
+ instance.initialize_properties(s, offset)
417
523
  instance.bitstream_properties.user_props = props
418
524
  initialize_instance(s, instance)
525
+ instance.initialize_with_fields
419
526
  return instance
420
527
  end
421
528
 
422
- #def method_missing(name, *args)
423
- # TODO: Support methods like "int16" "uint1"
424
- # super name, args
425
- #end
529
+ def method_missing(name, *args)
530
+ name_s = name.to_s
531
+ field_name = args.shift
532
+ if name_s =~ /^uint(\d+)$/
533
+ bit_width = Regexp.last_match[1].to_i
534
+ unsigned field_name, bit_width, *args
535
+ elsif name_s =~ /^int(\d+)$/
536
+ bit_width = Regexp.last_match[1].to_i
537
+ signed field_name, bit_width, *args
538
+ else
539
+ super name, args
540
+ end
541
+ end
426
542
 
427
543
  def instance(inherited_props, user_props = {})
428
544
  NestWrapper.new(self, inherited_props, user_props)
@@ -435,22 +551,35 @@ module BitStream
435
551
  obj.initialize_for_class_methods(ClassMethods.types)
436
552
  end
437
553
 
438
- def initialize(s, offset = 0)
554
+ def initialize_with_fields
555
+ # Nothing to do.
556
+ # Override me if you want to do anything after all fields has been defined.
557
+ end
558
+
559
+ def initialize_properties(s, offset = 0)
439
560
  props = Properties.new
440
561
  props.curr_offset = offset
441
562
  props.fields = {}
442
563
  props.raw_data = s
443
564
  props.initial_offset = offset
444
565
  props.eval_queue = Queue.new
566
+ props.substreams = Hash.new do |hash, key|
567
+ hash[key] = []
568
+ end
445
569
  @bitstream_properties = props
446
570
  end
447
571
 
448
572
  def length
449
- BitStream.index_all_fields(self)
450
573
  props = @bitstream_properties
574
+ queue = props.eval_queue
575
+ queue.peek_back.index unless queue.empty?
451
576
  props.curr_offset - props.initial_offset
452
577
  end
453
578
 
579
+ def substreams
580
+ @bitstream_properties.substreams.values
581
+ end
582
+
454
583
  #def properties=(props)
455
584
  # Method to override.
456
585
  #end
@@ -0,0 +1,117 @@
1
+ # Author:: Natsuki Kawai (natsuki.kawai@gmail.com)
2
+ # Copyright:: Copyright (c) 2012 Natsuki Kawai
3
+ # License:: 2-clause BSDL or Ruby's
4
+
5
+ class LazyString
6
+
7
+ # TODO: change name of SubString.
8
+ SubString = Struct.new(:start, :value)
9
+
10
+ class LazySubString
11
+
12
+ def initialize(value, start, size)
13
+ @start = start
14
+ @size = size
15
+ @value = value
16
+ end
17
+
18
+ def [](*args)
19
+ if args.size == 2
20
+ start = args[0]
21
+ length = args[1]
22
+ return @value[@start + start, length]
23
+ else
24
+ raise NotImplementedError
25
+ end
26
+ end
27
+
28
+ def to_str
29
+ @value[@start, @size].to_str
30
+ end
31
+ alias :to_s :to_str
32
+
33
+ attr_reader :size
34
+ alias :length :size
35
+
36
+ end
37
+
38
+ def initialize(*args)
39
+ @size = 0
40
+ @chain = []
41
+
42
+ if args.size == 3
43
+ @chain << SubString.new(0, LazySubString.new(*args))
44
+ @size = args[2]
45
+ end
46
+ end
47
+
48
+ # TODO: Add 'add' method to add a substring of a String.
49
+ def <<(other)
50
+ if other.respond_to?(:to_int)
51
+ return self << ('' << other)
52
+ end
53
+
54
+ @chain << SubString.new(@size, other)
55
+ @size += other.size
56
+ end
57
+
58
+ def [](*args)
59
+ if args.size == 2
60
+ start = args[0]
61
+ last = start + args[1]
62
+ length = args[1]
63
+ e = @chain.each
64
+
65
+ curr = nil
66
+ begin
67
+ curr = e.next
68
+ end while curr.start + curr.value.size < start
69
+
70
+ value = curr.value
71
+ sub_start = start - curr.start
72
+ sub_length = value.size - sub_start
73
+ if sub_length >= length
74
+ return LazyString.new(value, sub_start, length)
75
+ else
76
+ res = LazyString.new(value, sub_start, sub_length)
77
+ length -= sub_length
78
+ while length > 0
79
+ curr = e.next
80
+ if length < curr.value.length
81
+ res << LazyString.new(curr.value, 0, length)
82
+ length = 0
83
+ else
84
+ res << curr.value
85
+ length -= curr.value.length
86
+ end
87
+ end
88
+ return res
89
+ end
90
+ elsif args.respond_to?(:to_int)
91
+ warn "#{self.class.name}#[pos] has not implemented yet. Calling #{self.class.name}#to_str."
92
+ to_str[*args]
93
+ else # args is one Range object.
94
+ warn "#{self.class.name}#[range] has not implemented yet. Calling #{self.class.name}#to_str."
95
+ to_str[*args]
96
+ end
97
+ end
98
+
99
+ def unpack(template)
100
+ # TODO: Optimize here.
101
+ # (Stop concat the front strings if template start with "x".)
102
+ to_str.unpack(template)
103
+ end
104
+
105
+ def to_str
106
+ res = ''
107
+ @chain.each do |substr|
108
+ res << substr.value
109
+ end
110
+ return res
111
+ end
112
+ alias :to_s :to_str
113
+
114
+ attr_reader :size
115
+ alias :length :size
116
+
117
+ end
File without changes
data/test/test-array.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # Author:: Natsuki Kawai (natsuki.kawai@gmail.com)
2
- # Copyright:: Copyright 2011 Natsuki Kawai
2
+ # Copyright:: Copyright (c) 2011, 2012 Natsuki Kawai
3
3
  # License:: 2-clause BSDL or Ruby's
4
4
 
5
5
 
@@ -16,18 +16,60 @@ class ArraySample
16
16
 
17
17
  end
18
18
 
19
+ class InfiniteArraySample
20
+
21
+ include BitStream
22
+
23
+ fields do
24
+ array :a1, nil, :unsigned_int, 16
25
+ end
26
+
27
+ end
28
+
29
+ class VarlenArraySample
30
+
31
+ include BitStream
32
+
33
+ fields do
34
+ array :a1, nil, :cstring
35
+ end
36
+
37
+ end
38
+
19
39
  class TestArray < Test::Unit::TestCase
20
40
 
21
41
  def setup
22
42
  @spec = ArraySample.create "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a"
43
+ @spec_inf = InfiniteArraySample.create "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a"
44
+ @spec_var = VarlenArraySample.create "foo\0quux\0baz\0"
23
45
  end
24
46
 
25
47
  def test_a1
48
+ assert_equal(5, @spec.a1.size)
26
49
  assert_equal(0x0102, @spec.a1[0])
27
50
  assert_equal(0x0304, @spec.a1[1])
28
51
  assert_equal(0x0506, @spec.a1[2])
29
52
  assert_equal(0x0708, @spec.a1[3])
30
53
  assert_equal(0x090a, @spec.a1[4])
54
+ assert_equal(nil, @spec.a1[5])
55
+ end
56
+
57
+ def test_infinite
58
+ assert_equal(5, @spec_inf.a1.size)
59
+ assert_equal(0x0102, @spec_inf.a1[0])
60
+ assert_equal(0x0304, @spec_inf.a1[1])
61
+ assert_equal(0x0506, @spec_inf.a1[2])
62
+ assert_equal(0x0708, @spec_inf.a1[3])
63
+ assert_equal(0x090a, @spec_inf.a1[4])
64
+ assert_equal(nil, @spec_inf.a1[5])
65
+ end
66
+
67
+ def test_varlen
68
+ assert_equal(3, @spec_var.a1.size)
69
+ assert_equal("foo", @spec_var.a1[0])
70
+ assert_equal("quux", @spec_var.a1[1])
71
+ assert_equal("baz", @spec_var.a1[2])
72
+ assert_equal(nil, @spec_var.a1[3])
31
73
  end
32
74
 
33
75
  end
File without changes
@@ -0,0 +1,36 @@
1
+ # Author:: Natsuki Kawai (natsuki.kawai@gmail.com)
2
+ # Copyright:: Copyright (c) 2012 Natsuki Kawai
3
+ # License:: 2-clause BSDL or Ruby's
4
+
5
+ require 'test/unit'
6
+ require 'lazy-string'
7
+
8
+ class TestLazyString < Test::Unit::TestCase
9
+
10
+ def setup
11
+ @sample = LazyString.new
12
+ @sample << "foo"
13
+ @sample << "bar"
14
+ @sample << "quux"
15
+ @sample << "baz"
16
+ end
17
+
18
+ def test_head
19
+ assert_equal("fo", @sample[0, 2].to_str)
20
+ assert_equal("foo", @sample[0, 3].to_str)
21
+ assert_equal("foob", @sample[0, 4].to_str)
22
+ end
23
+
24
+ def test_im
25
+ assert_equal("a", @sample[4, 1].to_str)
26
+ assert_equal("bar", @sample[3, 3].to_str)
27
+ assert_equal("obarq", @sample[2, 5].to_str)
28
+ end
29
+
30
+ def test_last
31
+ assert_equal("az", @sample[11, 2].to_str)
32
+ assert_equal("baz", @sample[10, 3].to_str)
33
+ assert_equal("xbaz", @sample[9, 4].to_str)
34
+ end
35
+
36
+ end
@@ -0,0 +1,69 @@
1
+ # Author:: Natsuki Kawai (natsuki.kawai@gmail.com)
2
+ # Copyright:: Copyright (c) 2012 Natsuki Kawai
3
+ # License:: 2-clause BSDL or Ruby's
4
+
5
+ require 'test/unit'
6
+ require 'bitstream'
7
+
8
+ class OverloadSample1
9
+
10
+ include BitStream
11
+
12
+ fields do
13
+ unsigned :a, 32
14
+ unsigned :a, 32
15
+ end
16
+
17
+ end
18
+
19
+ class OverloadSample2
20
+
21
+ include BitStream
22
+
23
+ fields do
24
+ unsigned :a, 8
25
+ if a == 1
26
+ cstring :a
27
+ else
28
+ string :a, 1
29
+ end
30
+ end
31
+
32
+ end
33
+
34
+ class OverloadSampleArray
35
+
36
+ include BitStream
37
+
38
+ fields do
39
+ array :a, 3, :unsigned, 8
40
+ unsigned :a, 16
41
+ unsigned :b, 16
42
+ array :b, 2, :unsigned, 8
43
+ end
44
+
45
+ end
46
+
47
+ class TestOverload < Test::Unit::TestCase
48
+
49
+ def setup
50
+ @spec1 = OverloadSample1.create "\x00\x00\x00\x01\x00\x00\x00\x02"
51
+ @spec2 = OverloadSample2.create "\x01foo\0"
52
+ @spec_array = OverloadSampleArray.create "abc\x01\x01\x02\x02\x03\x03"
53
+ end
54
+
55
+ def test_a1
56
+ assert_equal(2, @spec1.a)
57
+ end
58
+
59
+ def test_a2
60
+ assert_equal("foo", @spec2.a)
61
+ end
62
+
63
+ def test_array
64
+ assert_equal(0x0101, @spec_array.a)
65
+ assert_equal([3, 3], @spec_array.b)
66
+ end
67
+
68
+ end
69
+
@@ -13,12 +13,12 @@ class SimpleIntBe
13
13
  byte_order :big_endian
14
14
 
15
15
  fields {
16
- unsigned_int "u1", 32
17
- unsigned_int :u2, 32
18
- cstring "cs1"
19
- unsigned_int "u3", 1
20
- unsigned_int "u4", 7
21
- string :s1, 3
16
+ unsigned "u1", 32
17
+ uint32 :u2
18
+ cstring "cs1"
19
+ unsigned "u3", 1
20
+ uint7 "u4"
21
+ string :s1, 3
22
22
  }
23
23
 
24
24
  end
data/test/test-suite.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # Author:: Natsuki Kawai (natsuki.kawai@gmail.com)
2
- # Copyright:: Copyright 2011 Natsuki Kawai
2
+ # Copyright:: Copyright (c) 2011, 2012 Natsuki Kawai
3
3
  # License:: 2-clause BSDL or Ruby's
4
4
 
5
5
 
@@ -7,6 +7,7 @@ require 'test/test-primitives'
7
7
  require 'test/test-array'
8
8
  require 'test/test-dynarray'
9
9
  require 'test/test-nesting'
10
+ require 'test/test-overload'
10
11
  require 'test/test-simple-properties'
11
12
  require 'test/types/test-character'
12
13
  require 'test/types/test-integer'
metadata CHANGED
@@ -1,89 +1,107 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: bitstream
3
- version: !ruby/object:Gem::Version
4
- version: 0.0.2
5
- prerelease:
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ - 0
9
+ version: 0.1.0
6
10
  platform: ruby
7
- authors:
11
+ authors:
8
12
  - Natsuki Kawai
9
13
  autorequire:
10
14
  bindir: bin
11
15
  cert_chain: []
12
- date: 2012-01-02 00:00:00.000000000 Z
13
- dependencies:
14
- - !ruby/object:Gem::Dependency
16
+
17
+ date: 2012-02-12 00:00:00 +09:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
15
21
  name: random-accessible
16
- requirement: &71448960 !ruby/object:Gem::Requirement
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
17
24
  none: false
18
- requirements:
19
- - - ! '>='
20
- - !ruby/object:Gem::Version
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ segments:
29
+ - 0
30
+ - 2
31
+ - 0
21
32
  version: 0.2.0
22
33
  type: :runtime
23
- prerelease: false
24
- version_requirements: *71448960
25
- description: ! 'BitStream is a mixin to write data structures of bit streams such
26
- as picture, music, movie files, and e.t.c.. You can refer contents of bit streams
27
- even when you are defining the data structures. With the function, you can write
28
- a data structure easily that the header contains the data length of the body field.
34
+ version_requirements: *id001
35
+ description: |
36
+ BitStream is a mixin to write data structures of bit streams such as picture, music, movie files, and e.t.c.. You can refer contents of bit streams even when you are defining the data structures. With the function, you can write a data structure easily that the header contains the data length of the body field.
29
37
 
30
- '
31
38
  email: natsuki.kawai@gmail.com
32
39
  executables: []
40
+
33
41
  extensions: []
34
- extra_rdoc_files:
42
+
43
+ extra_rdoc_files:
35
44
  - README.en
36
- files:
45
+ files:
37
46
  - lib/bitstream.rb
47
+ - lib/lazy-string.rb
38
48
  - lib/types/string.rb
39
- - lib/types/utils.rb
40
- - lib/types/character.rb
49
+ - lib/types/cstring.rb
41
50
  - lib/types/string-utils.rb
51
+ - lib/types/character.rb
42
52
  - lib/types/integer.rb
43
- - lib/types/cstring.rb
44
- - lib/types/basetype.rb
53
+ - test/test-overload.rb
45
54
  - test/test-nesting.rb
46
55
  - test/test-dynarray.rb
47
- - test/test-condition.rb
48
- - test/test-simple-properties.rb
49
56
  - test/test-suite.rb
50
- - test/test-array.rb
51
57
  - test/test-primitives.rb
52
- - test/types/test-utils.rb
53
- - test/types/test-character.rb
54
- - test/types/test-cstring.rb
58
+ - test/test-simple-properties.rb
59
+ - test/test-condition.rb
60
+ - test/test-lazy-string.rb
61
+ - test/test-array.rb
55
62
  - test/types/test-string.rb
56
63
  - test/types/test-integer.rb
57
- - sample/gzip.rb
64
+ - test/types/test-character.rb
65
+ - test/types/test-cstring.rb
58
66
  - sample/flac.rb
67
+ - sample/gzip.rb
59
68
  - sample/gzip-viewer.rb
60
- - sample/front.rb
69
+ - sample/flac-front.rb
61
70
  - README.en
71
+ has_rdoc: true
62
72
  homepage: https://github.com/natsuki14/bitstream
63
- licenses:
73
+ licenses:
64
74
  - Ruby's
65
75
  - 2-clause BSDL
66
76
  post_install_message:
67
77
  rdoc_options: []
68
- require_paths:
78
+
79
+ require_paths:
69
80
  - lib
70
- required_ruby_version: !ruby/object:Gem::Requirement
81
+ required_ruby_version: !ruby/object:Gem::Requirement
71
82
  none: false
72
- requirements:
73
- - - ! '>='
74
- - !ruby/object:Gem::Version
83
+ requirements:
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ segments:
87
+ - 1
88
+ - 9
89
+ - 1
75
90
  version: 1.9.1
76
- required_rubygems_version: !ruby/object:Gem::Requirement
91
+ required_rubygems_version: !ruby/object:Gem::Requirement
77
92
  none: false
78
- requirements:
79
- - - ! '>='
80
- - !ruby/object:Gem::Version
81
- version: '0'
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ segments:
97
+ - 0
98
+ version: "0"
82
99
  requirements: []
100
+
83
101
  rubyforge_project:
84
- rubygems_version: 1.8.11
102
+ rubygems_version: 1.3.7
85
103
  signing_key:
86
104
  specification_version: 3
87
105
  summary: A bitstream parser supports dynamic-defined fields
88
- test_files:
106
+ test_files:
89
107
  - test/test-suite.rb
@@ -1,9 +0,0 @@
1
- module BitStream
2
-
3
- module SingleType
4
- def instance
5
-
6
- end
7
- end
8
-
9
- end
data/lib/types/utils.rb DELETED
@@ -1,26 +0,0 @@
1
- module BitStream
2
-
3
- module Utils
4
-
5
- def self.align(s, offset, length)
6
- index = offset
7
- bitoffset = offset % 8
8
- aligned = nil
9
- if bitoffset != 0
10
- aligned = ""
11
- while index < offset + length
12
- i = index / 8
13
- c = s[i..(i + 1)].unpack('n')[0] >> (8 - bitoffset)
14
- aligned << [c].pack('C')
15
- index += 8
16
- end
17
- else
18
- aligned = s[(offset / 8)...((offset + length) / 8)]
19
- end
20
- return aligned
21
- end
22
-
23
- end
24
-
25
- end
26
-
@@ -1,36 +0,0 @@
1
- require 'test/unit'
2
- require 'types/utils'
3
-
4
- class TestUtils < Test::Unit::TestCase
5
-
6
- def test_align_aligned_bytelen
7
- source = "abcde"
8
- aligned = BitStream::Utils.align(source, 8, 8 * 3)
9
- assert_equal("bcd", aligned)
10
- end
11
-
12
- def test_align_aligned_bytelen_lastbyte
13
- source = "abcde"
14
- aligned = BitStream::Utils.align(source, 8 * 2, 8 * 3)
15
- assert_equal("cde", aligned)
16
- end
17
-
18
- def test_align_aligned
19
- source = "defghi"
20
- aligned = BitStream::Utils.align(source, 8 * 2, 8 * 2 + 6)
21
- assert_equal(3, aligned.size)
22
- aligned = aligned.unpack("a2C")
23
- assert_equal("fg", aligned[0])
24
- assert_equal("h".ord & 0b11111100, aligned[1] & 0b11111100)
25
- end
26
-
27
- def test_align_aligned_lastbyte
28
- source = "defghi"
29
- aligned = BitStream::Utils.align(source, 8 * 3, 8 * 2 + 6)
30
- assert_equal(3, aligned.size)
31
- aligned = aligned.unpack("a2C")
32
- assert_equal("gh", aligned[0])
33
- assert_equal("i".ord & 0b11111100, aligned[1] & 0b11111100)
34
- end
35
-
36
- end