Class: BinaryParser::StreamTemplateBase

Inherits:
Object
  • Object
show all
Includes:
BuiltInTemplate
Defined in:
lib/binary_parser/stream_template_base.rb

Constant Summary

Constants included from BuiltInTemplate

BuiltInTemplate::BCD, BuiltInTemplate::BCD_f1, BuiltInTemplate::BCD_f10, BuiltInTemplate::BCD_f2, BuiltInTemplate::BCD_f3, BuiltInTemplate::BCD_f4, BuiltInTemplate::BCD_f5, BuiltInTemplate::BCD_f6, BuiltInTemplate::BCD_f7, BuiltInTemplate::BCD_f8, BuiltInTemplate::BCD_f9

Class Method Summary collapse

Instance Method Summary collapse

Methods included from BuiltInTemplate

bcd_make

Constructor Details

#initialize(binary_stream, filters = []) ⇒ StreamTemplateBase

Returns a new instance of StreamTemplateBase.



30
31
32
33
34
35
36
37
38
# File 'lib/binary_parser/stream_template_base.rb', line 30

def initialize(binary_stream, filters=[])
  case binary_stream
  when BufferedStream
    @buffered_binary_stream = binary_stream
  else
    @buffered_binary_stream = BufferedStream.new(binary_stream, self.class.get_buffer_size)
  end
  @filters = filters
end

Class Method Details

.Def(byte_length, buffer_num = 10000, &definition_proc) ⇒ Object



11
12
13
# File 'lib/binary_parser/stream_template_base.rb', line 11

def self.Def(byte_length, buffer_num=10000, &definition_proc)
  def_stream(byte_length, buffer_num, &definition_proc)
end

.def_stream(byte_length, buffer_num = 10000, &definition_proc) ⇒ Object



5
6
7
8
9
# File 'lib/binary_parser/stream_template_base.rb', line 5

def self.def_stream(byte_length, buffer_num=10000, &definition_proc)
  @byte_length = byte_length
  @buffer_size = buffer_num * byte_length
  @template = NamelessTemplateMaker.new(definition_proc)
end

.get_buffer_sizeObject



25
26
27
28
# File 'lib/binary_parser/stream_template_base.rb', line 25

def self.get_buffer_size
  raise BadManipulationError, "Buffer-size is undefined." unless @buffer_size
  return @buffer_size
end

.get_byte_lengthObject



20
21
22
23
# File 'lib/binary_parser/stream_template_base.rb', line 20

def self.get_byte_length
  raise BadManipulationError, "Byte-length is undefined." unless @byte_length
  return @byte_length
end

.get_templateObject



15
16
17
18
# File 'lib/binary_parser/stream_template_base.rb', line 15

def self.get_template
  raise BadManipulationError, "Structure is undefined." unless @template
  return @template
end

Instance Method Details

#accumulate(init_amount, dest_amount, &reduce_proc) ⇒ Object

Accumulate elements Concrete example:

If stream has [1, 2, 3, 4, 5, ...] and given reduce_proc is Proc.new{|acc, a| acc + a},
accumulate(0, 6, &reduce_proc) returns array of [1, 2, 3] and then stream has[4, 5, ...].

Special case: If enough elements don’t remain, this method returns nil.

Example: [1, 2, 3], accumulate(0, 7, &reduce_proc) => return: nil, stream: [] (end)


152
153
154
155
156
157
158
159
160
161
# File 'lib/binary_parser/stream_template_base.rb', line 152

def accumulate(init_amount, dest_amount, &reduce_proc)
  raise BadManipulationError, "Reduce Proc isn't given." unless reduce_proc
  accumulation, amount = [], init_amount
  while amount < dest_amount
    return nil unless rest?
    accumulation << get_next
    amount = reduce_proc.call(amount, accumulation.last)
  end
  return accumulation
end

#closeObject

Simply close binary-stream.



177
178
179
# File 'lib/binary_parser/stream_template_base.rb', line 177

def close
  @buffered_binary_stream.close
end

#eofObject



172
173
174
# File 'lib/binary_parser/stream_template_base.rb', line 172

def eof
  eof?
end

#eof?Boolean

Returns:

  • (Boolean)


168
169
170
# File 'lib/binary_parser/stream_template_base.rb', line 168

def eof?
  !rest?
end

#filter(&filter_proc) ⇒ Object

Add fileter to instance (not disruptive) return: new instance which has filter



42
43
44
45
# File 'lib/binary_parser/stream_template_base.rb', line 42

def filter(&filter_proc)
  raise BadManipulationError, "Filter Proc isn't given." unless filter_proc
  return self.class.new(@buffered_binary_stream, @filters + [filter_proc])
end

#filtered_simply_get_next(filters) ⇒ Object



67
68
69
70
71
72
73
# File 'lib/binary_parser/stream_template_base.rb', line 67

def filtered_simply_get_next(filters)
  begin
    structure = simply_get_next
    return nil unless structure
  end until filters.all?{|filter| filter.call(structure)}
  return structure
end

#get_nextObject

Get next element from binary-stream. If instance has filters, the unsatisfied element is to be abandoned

and recursively returns next element.

Special cases:

(1) If rest of binary-stream's length is 0, this method returns nil.
(2) If rest of binary-stream's length is shorter than required,
    this method throws ParsingError.


54
55
56
# File 'lib/binary_parser/stream_template_base.rb', line 54

def get_next
  return take_lookahead || filtered_simply_get_next(@filters)
end

#get_sequence(allow_incomplete_sequence = false, &cond_proc) ⇒ Object

Get sequence by specifing head-condition. Concrete example:

If stream has [F1, T2, F3, F4, T5, ...] and given cond_proc is Proc.new{|a| a == Tx},
get_sequence(&cond_proc) returns array of [T2, F3, F4] and then stream has [T5, ...].

In the same way, (1) [T1, F2, T3, ...] => return: [T1, F2], stream: [T3, ...]
                 (2) [T1, T2, F3, ...] => return: [T1],     stream: [T2, F3, ...]
                 (3) [T1, F2]          => return: [],       stream: [] (end)
                 (4) [F1, F2]          => return: [],       stream: [] (end)
                 (5) [] (end)          => return: [],       stream: [] (end)

* But if option-arg "allow_incomplete_sequence" is set as true, above example of (3) is
                     [T1, F2, F3, F4]  => return: [T1, F2, F3, F4], stream: [] (end)


136
137
138
139
140
141
142
143
# File 'lib/binary_parser/stream_template_base.rb', line 136

def get_sequence(allow_incomplete_sequence = false, &cond_proc)
  raise BadManipulationError, "Condition Proc isn't given." unless cond_proc
  seek_top(&cond_proc)
  return [] unless rest?
  res = [get_next] + seek_top(&cond_proc)
  return [] unless rest? || allow_incomplete_sequence
  return res
end

#next_binaryObject



80
81
82
83
84
85
86
87
# File 'lib/binary_parser/stream_template_base.rb', line 80

def next_binary
  binary = @buffered_binary_stream.read(self.class.get_byte_length)
  if binary && binary.length < self.class.get_byte_length
    raise ParsingError, "Stream's rest binary length" + 
      "(#{binary.length} byte) is shorter than required length (#{self.class.get_byte_length} byte)."
  end
  return binary
end

#non_proceed_get_nextObject



58
59
60
# File 'lib/binary_parser/stream_template_base.rb', line 58

def non_proceed_get_next
  @lookahead ||= get_next
end

#read(n) ⇒ Object

Take n elements from stream. Behave like calling #get_next n times. Special cases:

(1) If n elements do NOT exist in stream (only m elements exist), 
    this method take m (< n) elements from stream.


93
94
95
96
97
98
99
100
101
102
103
# File 'lib/binary_parser/stream_template_base.rb', line 93

def read(n)
  res = []
  n.times do
    if rest?
      res << get_next
    else
      break
    end
  end
  return res
end

#rest?Boolean

Check whether binary-stream remains or not.

Returns:

  • (Boolean)


164
165
166
# File 'lib/binary_parser/stream_template_base.rb', line 164

def rest?
  non_proceed_get_next
end

#seek_top(&cond_proc) ⇒ Object

Remove elements until finding element which fullfils proc-condition or reaching end of stream. return: array of removed elements

Concrete example:

If stream has [F1, F2, T3, F4, ...] and given cond_proc is Proc.new{|a| a == Tx},
seek_top(&cond_proc) returns array of [F1, F2] and then stream has [T3, F4, ...].
In the same way, (1) [T1, F2, ...] => return: [],       stream: [T1, F2, ...]
                 (2) [F1, F2]      => return: [F1, F2], stream: [] (end)
                 (3) [] (end)      => return: [],       stream: [] (end)


114
115
116
117
118
119
120
121
# File 'lib/binary_parser/stream_template_base.rb', line 114

def seek_top(&cond_proc)
  raise BadManipulationError, "Condition Proc isn't given." unless cond_proc
  abandoned = []
  until !rest? || cond_proc.call(non_proceed_get_next)
    abandoned << take_lookahead
  end
  return abandoned
end

#simply_get_nextObject



75
76
77
78
# File 'lib/binary_parser/stream_template_base.rb', line 75

def simply_get_next
  return nil unless binary = next_binary
  self.class.get_template.new(binary)
end

#take_lookaheadObject



62
63
64
65
# File 'lib/binary_parser/stream_template_base.rb', line 62

def take_lookahead
  res, @lookahead = @lookahead, nil
  return res
end