class Bismas::Parser
-
Each record is terminated by
0x0D
0x0A
(CHARS[:newline]
). -
Each record starts with
0x01
(CHARS[:rs]
) or, if it's a deleted record, with0xFF
(CHARS[:deleted]
). -
Each field is terminated by
0x00
(CHARS[:fs]
). -
Each field starts with the category “number”, a run of
category_length
characters except0x00
,0x01
,0xDB
or0xFF
; trailing space is stripped. -
The remaining characters of a field form the category content; trailing padding
0xDB
(CHARS[:padding]
) is stripped.
To quote the BISMAS handbook: “Konkret wird bei BISMAS jeder Datensatz durch ASCII(1) eingeleitet. Es folgt die erste Kategorienummer mit dem Kategorieinhalt. Abgeschlossen wird jede Kategorie mit ASCII(0), danach folgt die nächste Kategorienummer und -inhalt usw. Der gesamte Datensatz wird mit ASCII (13)(10) abgeschlossen.”
Public Class Methods
# File lib/bismas/parser.rb, line 79 def initialize(options = {}) @regex = Bismas.regex(options) @strict, @silent = options.values_at(:strict, :silent) end
# File lib/bismas/parser.rb, line 74 def self.parse(io, options = {}, &block) klass = options[:legacy] ? Legacy : self klass.new(options).parse(io, &block) end
Public Instance Methods
# File lib/bismas/parser.rb, line 85 def parse(io, &block) @input = StringScanner.new('') io.each { |input| @input << input parse_record(&block) while @input.check_until(@regex[:newline]) @input.string = @input.string.byteslice(@input.pos..-1) } error('Unexpected data') unless @input.eos? self end
# File lib/bismas/parser.rb, line 115 def parse_field k = match(:category, 0) and k.rstrip! v = match(:field, 1) or error(k ? "Unclosed field `#{k}'" : 'Unexpected data', :rest) k ? block_given? ? yield(k, v) : [k, v] : v.empty? ? nil : error('Malformed field', :field) end
# File lib/bismas/parser.rb, line 100 def parse_record if match(:deleted) match(:skip_line) return elsif !match_record error('Malformed record', :line) return end r = Hash.new { |h, k| h[k] = [] } parse_field { |k, v| r[k] << v } until match(:newline) block_given? ? yield(r) : r end
Private Instance Methods
# File lib/bismas/parser.rb, line 136 def error(message, skip = nil) err = parse_error(message) raise err unless skip && !@strict warn err.to_s unless @silent match(:"skip_#{skip}") nil end
# File lib/bismas/parser.rb, line 127 def match(key, index = nil) res = @input.skip(@regex.fetch(key)) res && index ? @input[index] : res end
# File lib/bismas/parser.rb, line 132 def match_record match(:rs) end
# File lib/bismas/parser.rb, line 145 def parse_error(message) ParseError.new(@input, message) end