module Dnsruby::BitMapping

Provides methods for converting between the various representations of a bitmap: number, binary encoded string, array, and sparse array.

Where an array is used to represent bits, the first element (#0) will be the low (1) bit and the last bit will be the high bit.

Public Instance Methods

assert_non_negative(number) click to toggle source

If number is negative, raises an ArgumentError; else does nothing.

# File lib/dnsruby/bit_mapping.rb, line 120
def assert_non_negative(number)
  unless number.is_a?(Integer) && number >= 0
    raise ArgumentError.new(
              "Parameter must be a nonnegative Integer " +
                  "but is #{number.inspect} (a #{number.class})")
  end
end
binary_string_to_bit_array(string, minimum_binary_places = 0) click to toggle source

Converts a binary string to an array of bit values, e.g. “x0C” => [1, 1, 0, 0]

# File lib/dnsruby/bit_mapping.rb, line 113
def binary_string_to_bit_array(string, minimum_binary_places = 0)
  number = binary_string_to_number(string)
  number_to_bit_array(number, minimum_binary_places)
end
binary_string_to_number(string) click to toggle source

Converts from a binary string to a number, e.g. “x01x00” => 256

# File lib/dnsruby/bit_mapping.rb, line 17
def binary_string_to_number(string)
  string = string.clone.force_encoding(Encoding::ASCII_8BIT)
  string.bytes.inject(0) do |number, byte|
    number * 256 + byte.ord
  end
end
bit_array_to_number(bit_array) click to toggle source

Converts an array of bit values, e.g. [1, 0, 0, 1], to a number, e.g. 9

# File lib/dnsruby/bit_mapping.rb, line 76
def bit_array_to_number(bit_array)
  return nil if bit_array.empty?
  multiplier = 1
  bit_array.reverse.inject(0) do |result, n|
    result += n * multiplier
    multiplier *= 2
    result
  end
end
number_to_binary_string(number, min_length = 0) click to toggle source

Converts a number to a binary encoded string, e.g. 256 => “x01x00”

# File lib/dnsruby/bit_mapping.rb, line 26
def number_to_binary_string(number, min_length = 0)
  assert_non_negative(number)
  binary_string = ''.force_encoding(Encoding::ASCII_8BIT)

  while number > 0
    byte_value = number & 0xFF
    binary_string << byte_value
    number >>= 8
  end

  binary_string.reverse.rjust(min_length, "\x00")
end
number_to_bit_array(number, minimum_binary_places = 0) click to toggle source

Converts a number to an array of bit values, e.g. 9 => [1, 0, 0, 1]

# File lib/dnsruby/bit_mapping.rb, line 61
def number_to_bit_array(number, minimum_binary_places = 0)
  assert_non_negative(number)
  array = []
  while number > 0
    array << (number & 1)
    number >>= 1
  end
  array.reverse!
  zero_pad_count = minimum_binary_places - array.size
  zero_pad_count.times { array.unshift(0) }
  array
end
number_to_place_value_array(number) click to toggle source

Converts a number to an array of place values, e.g. 9 => [8, 0, 0, 1]

# File lib/dnsruby/bit_mapping.rb, line 41
def number_to_place_value_array(number)
  assert_non_negative(number)
  array = []
  bit_value = 1
  while number > 0
    array << ((number & 1 == 1) ? bit_value : 0)
    number >>= 1
    bit_value <<= 1
  end
  array.reverse
end
number_to_set_bit_positions_array(number) click to toggle source

Converts a number to a sparse array containing bit positions that are set/true/1. Note that these are bit positions, e.g. 76543210, and not bit column values such as 128/64/32/16/8/4/2/1.

# File lib/dnsruby/bit_mapping.rb, line 90
def number_to_set_bit_positions_array(number)
  assert_non_negative(number)
  array = []
  position = 0
  while number > 0
    array << position if number & 1 == 1
    position += 1
    number >>= 1
  end
  array
end
place_value_array_to_number(place_value_array) click to toggle source

Converts from a value array to a number, e.g. [8, 0, 0, 1] => 9

# File lib/dnsruby/bit_mapping.rb, line 55
def place_value_array_to_number(place_value_array)
  place_value_array.inject(&:+)
end
reverse_binary_string_bits(binary_string) click to toggle source

Reverses a binary string. Note that it is not enough to reverse the string itself because although the bytes would be reversed, the bits within each byte would not.

# File lib/dnsruby/bit_mapping.rb, line 131
def reverse_binary_string_bits(binary_string)
  binary_place_count = binary_string.size * 8
  reversed_bit_array = binary_string_to_bit_array(binary_string, binary_place_count).reverse
  number = bit_array_to_number(reversed_bit_array)
  number_to_binary_string(number)
end
set_bit_position_array_to_number(position_array) click to toggle source

Converts an array of bit position numbers to a numeric value, e.g. [0, 2] => 5

# File lib/dnsruby/bit_mapping.rb, line 104
def set_bit_position_array_to_number(position_array)
  return nil if position_array.empty?
  position_array.inject(0) do |result, n|
    result += 2 ** n
  end
end