Module: Dnsruby::BitMapping

Defined in:
lib/dnsruby/bit_mapping.rb

Overview

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.

Class Method Summary collapse

Class Method Details

.assert_non_negative(number) ⇒ Object

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



120
121
122
123
124
125
126
# 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) ⇒ Object

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



113
114
115
116
# 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) ⇒ Object

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



17
18
19
20
21
22
# File 'lib/dnsruby/bit_mapping.rb', line 17

def binary_string_to_number(string)
  string = string.b
  string.bytes.inject(0) do |number, byte|
    number * 256 + byte.ord
  end
end

.bit_array_to_number(bit_array) ⇒ Object

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



76
77
78
79
80
81
82
83
84
# 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) ⇒ Object

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



26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/dnsruby/bit_mapping.rb', line 26

def number_to_binary_string(number, min_length = 0)
  assert_non_negative(number)
  binary_string = ''.b

  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) ⇒ Object

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



61
62
63
64
65
66
67
68
69
70
71
72
# 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) ⇒ Object

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



41
42
43
44
45
46
47
48
49
50
51
# 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) ⇒ Object

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.



90
91
92
93
94
95
96
97
98
99
100
# 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) ⇒ Object

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



55
56
57
# 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) ⇒ Object

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.



131
132
133
134
135
136
# 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) ⇒ Object

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



104
105
106
107
108
109
# 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