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[R]

additional_bitmap defines if the bit 1 (left to right) indicates the presence of another bitmap just after the current one

bitmap_size[R]

bitmap_size defines the size in bits of bitmap. It has to be multiple of 8 (a byte of 8 bits)

bitmaps[R]

Public Class Methods

new(message = nil, hex_bitmap=false, bitmap_size = 64, additional_bitmap = true) click to toggle source

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(str, hex_bitmap = false, bitmap_size = 64) click to toggle source

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

[](i) click to toggle source

Returns whether the bit is set or not.

# File lib/iso8583/bitmap.rb, line 72
def [](i)
  @bmp[i-1]
end
additional_bitmap?() click to toggle source
# File lib/iso8583/bitmap.rb, line 58
def additional_bitmap?
  !!@additional_bitmap
end
each() { |each bit set in the bitmap except the first bit.| ... } click to toggle source

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
hex_bitmap?() click to toggle source
# File lib/iso8583/bitmap.rb, line 62
def hex_bitmap?
  !!@hex_bitmap
end
set(i) click to toggle source

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
size_in_bits() click to toggle source
# File lib/iso8583/bitmap.rb, line 98
def size_in_bits
  bitmaps * bitmap_size
end
size_in_bytes() click to toggle source
# File lib/iso8583/bitmap.rb, line 102
def size_in_bytes
  size_in_bits / 8
end
size_in_bytes_hex() click to toggle source
# File lib/iso8583/bitmap.rb, line 106
def size_in_bytes_hex
  size_in_bytes * 2
end
to_b()
Alias for: to_bytes
to_bytes() click to toggle source

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
Also aliased as: to_b
to_hex() click to toggle source
# 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
to_s() click to toggle source

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
unset(i) click to toggle source

Unsets bit i

# File lib/iso8583/bitmap.rb, line 111
def unset(i)
  self[i] = false
end

Private Instance Methods

[]=(i, value) click to toggle source

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
convert_hex_to_binary(str) click to toggle source
# 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
initialize_from_message(message) click to toggle source
# 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