class ISO8583::Bitmap
This class constructs an object for handling bitmaps with which ISO8583
messages typically begin. Bitmaps are either 8 or 16 bytes long, an extended length bitmap is indicated by the first bit being set. In all likelyhood, you won't be using this class much, it's used transparently by the Message
class.
Attributes
additional_bitmap
defines if the bit 1 (left to right) indicates the presence of another bitmap just after the current one
bitmap_size
defines the size in bits of bitmap. It has to be multiple of 8 (a byte of 8 bits)
Public Class Methods
create a new Bitmap
object. In case an iso message is passed in, that messages bitmap will be parsed. If not, this initializes and empty bitmap.
# File lib/iso8583/bitmap.rb, line 46 def initialize(message = nil, hex_bitmap=false, bitmap_size = 64, additional_bitmap = true) raise ISO8583Exception.new "wrong bitmap_size: #{bitmap_size}" if bitmap_size % 8 != 0 @bitmap_size = bitmap_size @bmp = Array.new(bitmap_size, false) @hex_bitmap = hex_bitmap @additional_bitmap = additional_bitmap @bitmaps = 1 message ? initialize_from_message(message) : nil end
Parse the bytes in string and return the Bitmap
and bytes remaining in `str` after the bitmap is taken away.
# File lib/iso8583/bitmap.rb, line 21 def parse(str, hex_bitmap = false, bitmap_size = 64) bmp = Bitmap.new(str, hex_bitmap, bitmap_size) rest = if bmp.hex_bitmap? str[bmp.size_in_bytes_hex, str.length] else str[bmp.size_in_bytes, str.length] end [ bmp, rest ] end
Public Instance Methods
Returns whether the bit is set or not.
# File lib/iso8583/bitmap.rb, line 72 def [](i) @bmp[i-1] end
# File lib/iso8583/bitmap.rb, line 58 def additional_bitmap? !!@additional_bitmap end
yield once with the number of each set field.
# File lib/iso8583/bitmap.rb, line 67 def each #:yields: each bit set in the bitmap except the first bit. @bmp[1..-1].each_with_index {|set, i| yield i+2 if set} end
# File lib/iso8583/bitmap.rb, line 62 def hex_bitmap? !!@hex_bitmap end
Sets bit i
# File lib/iso8583/bitmap.rb, line 77 def set(i) if additional_bitmap? raise ISO8583Exception, "field #{i} shouldn't be set (continuation bit is set automatically)" if i % bitmap_size == 1 end if i > bitmap_size raise ISO8583Exception, "can't set field #{i}, bitmap_size == #{bitmap_size}" unless additional_bitmap? quo = i / bitmap_size rem = i % bitmap_size @bitmaps = rem > 0 ? quo + 1 : quo new_bmp = Array.new(@bitmaps * bitmap_size, false) @bmp.each_with_index { |v, idx| new_bmp[idx] = v } 0.upto(@bitmaps - 2) do |pos| new_bmp[pos * bitmap_size] = true end @bmp = new_bmp end self[i] = true end
# File lib/iso8583/bitmap.rb, line 98 def size_in_bits bitmaps * bitmap_size end
# File lib/iso8583/bitmap.rb, line 102 def size_in_bytes size_in_bits / 8 end
# File lib/iso8583/bitmap.rb, line 106 def size_in_bytes_hex size_in_bytes * 2 end
Generate the bytes representing this bitmap.
# File lib/iso8583/bitmap.rb, line 116 def to_bytes if RUBY_ENGINE == 'mruby' # Convert binary to hex, by slicing the binary in 4 bytes chuncks bitmap_hex = "" str = String.new("", encoding: 'ASCII-8BIT') self.to_s.chars.reverse.each_with_index do |ch, i| str << ch next if i == 0 if (i+1) % 4 == 0 bitmap_hex << str.reverse.to_i(2).to_s(16) str = String.new("", encoding: 'ASCII-8BIT') end end unless str.empty? bitmap_hex << str.reverse.to_i(2).to_s(16) end bitmap_hex.reverse.upcase else [to_s].pack("B*") end end
# File lib/iso8583/bitmap.rb, line 139 def to_hex self.to_s.to_i(2).to_s(16).upcase.ljust(size_in_bytes_hex, '0') end
Generate a String
representation of this bitmap in the form:
01001100110000011010110110010100100110011000001101011011001010
# File lib/iso8583/bitmap.rb, line 145 def to_s str = String.new("", encoding: "ASCII-8BIT") 1.upto(size_in_bits) do |i| str << (self[i] ? '1' : '0') end str end
Unsets bit i
# File lib/iso8583/bitmap.rb, line 111 def unset(i) self[i] = false end
Private Instance Methods
Set the bit to the indicated value. Only `true` sets the bit, any other value unsets it.
# File lib/iso8583/bitmap.rb, line 159 def []=(i, value) @bmp[i-1] = (value == true) end
# File lib/iso8583/bitmap.rb, line 163 def convert_hex_to_binary(str) str.chars.reverse.inject("") do |string, ch| string + ch.to_i(16).to_s(2).rjust(4, "0").reverse end.reverse end
# File lib/iso8583/bitmap.rb, line 169 def initialize_from_message(message) bmp = if hex_bitmap? slice_range = (bitmap_size * 2) / 8 - 1 rjust(convert_hex_to_binary(message[0..slice_range]), bitmap_size, '0') else message.unpack("B#{bitmap_size}")[0] end if additional_bitmap? has_next_bitmap = bmp[0] == "1" while has_next_bitmap @bitmaps += 1 bmp = if hex_bitmap? slice_range = (bitmap_size * bitmaps * 2) / 8 - 1 rjust(convert_hex_to_binary(message[0..slice_range]), bitmap_size * bitmaps, '0') else message.unpack("B#{bitmap_size * bitmaps}")[0] end has_next_bitmap = bmp[bitmap_size * (bitmaps - 1)] == "1" end end 0.upto(bmp.length-1) do |i| @bmp[i] = (bmp[i,1] == "1") end end