Class: BinaryParser::StreamTemplateBase
- Inherits:
-
Object
- Object
- BinaryParser::StreamTemplateBase
- Includes:
- BuiltInTemplate
- Defined in:
- lib/stream_template_base.rb
Class Method Summary collapse
- .Def(byte_length, &definition_proc) ⇒ Object
- .def_stream(byte_length, &definition_proc) ⇒ Object
- .get_stream_definition ⇒ Object
Instance Method Summary collapse
-
#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, …].
-
#close ⇒ Object
Simply close binary-stream.
-
#filter(&filter_proc) ⇒ Object
Add fileter to instance (not disruptive) return: new instance which has filter.
-
#get_next ⇒ Object
Get next element from binary-stream.
-
#get_sequence(allow_incomplete_sequence = false, &cond_proc) ⇒ Object
Get sequence by specifing head-condition.
-
#initialize(binary_stream, filters = []) ⇒ StreamTemplateBase
constructor
A new instance of StreamTemplateBase.
-
#rest? ⇒ Boolean
Check whether binary-stream remains or not.
-
#seek_top(&cond_proc) ⇒ Object
Remove elements until finding element which fullfils proc-condition or reaching end of stream.
Constructor Details
#initialize(binary_stream, filters = []) ⇒ StreamTemplateBase
Returns a new instance of StreamTemplateBase.
18 19 20 21 |
# File 'lib/stream_template_base.rb', line 18 def initialize(binary_stream, filters=[]) @binary_stream = binary_stream @filters = filters end |
Class Method Details
.Def(byte_length, &definition_proc) ⇒ Object
11 |
# File 'lib/stream_template_base.rb', line 11 def self.Def(byte_length, &definition_proc) def_stream(byte_length, &definition_proc) end |
.def_stream(byte_length, &definition_proc) ⇒ Object
5 6 7 8 9 |
# File 'lib/stream_template_base.rb', line 5 def self.def_stream(byte_length, &definition_proc) @byte_length = byte_length used_method_names = NamelessTemplate.instance_methods + Scope.instance_methods @structure = StructureDefinition.new(used_method_names, &definition_proc) end |
.get_stream_definition ⇒ Object
13 14 15 16 |
# File 'lib/stream_template_base.rb', line 13 def self.get_stream_definition raise BadManipulationError, "Stream is undefined." unless @byte_length && @structure return @byte_length, @structure 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)
108 109 110 111 112 113 114 115 116 117 |
# File 'lib/stream_template_base.rb', line 108 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 |
#close ⇒ Object
Simply close binary-stream.
125 126 127 |
# File 'lib/stream_template_base.rb', line 125 def close @binary_stream.close end |
#filter(&filter_proc) ⇒ Object
Add fileter to instance (not disruptive) return: new instance which has filter
25 26 27 28 |
# File 'lib/stream_template_base.rb', line 25 def filter(&filter_proc) raise BadManipulationError, "Filter Proc isn't given." unless filter_proc return self.class.new(@binary_stream, @filters + [filter_proc]) end |
#get_next ⇒ Object
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 BadBinaryManipulationError.
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
# File 'lib/stream_template_base.rb', line 37 def get_next begin if @lookahead scope, @lookahead = @lookahead, nil else byte_length, structure = self.class.get_stream_definition binary = @binary_stream.read(byte_length) return nil unless binary if binary.length < byte_length raise ParsingError, "Stream's rest binary length" + "(#{binary.length} byte) is shorter than required length (#{byte_length} byte)." end abstract_binary = AbstractBinary.new(binary) scope = Scope.new(structure, abstract_binary) end end until @filters.all?{|filter| filter.call(scope)} return NamelessTemplate.new(scope) 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)
92 93 94 95 96 97 98 99 |
# File 'lib/stream_template_base.rb', line 92 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 |
#rest? ⇒ Boolean
Check whether binary-stream remains or not.
120 121 122 |
# File 'lib/stream_template_base.rb', line 120 def rest? return @lookahead || !@binary_stream.eof? 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)
65 66 67 68 69 70 71 72 73 74 75 76 77 |
# File 'lib/stream_template_base.rb', line 65 def seek_top(&cond_proc) raise BadManipulationError, "Condition Proc isn't given." unless cond_proc abandoned = [] until @lookahead && cond_proc.call(@lookahead) if @lookahead abandoned << @lookahead @lookahead = nil end return abandoned unless rest? @lookahead = get_next end return abandoned end |