Class: BitMagic::BitField

Inherits:
Object
  • Object
show all
Defined in:
lib/bit_magic/bit_field.rb

Overview

Helper class to encapsulate bit field values and read/write operations Note that indices are based off ruby bit reading, so least-significant bits are to the right and negative numbers are handled as two’s complement.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(value = 0) ⇒ BitField

Initialize the BitField with an optional value. Default is 0

Parameters:

  • value (Integer) (defaults to: 0)

    the integer that contains the bit fields



16
17
18
19
20
21
22
# File 'lib/bit_magic/bit_field.rb', line 16

def initialize(value = 0)
  if value.is_a?(Integer)
    @value = value
  else
    raise InputError.new("BitField#new expects an integer value, #{value.inspect} is not an integer")
  end
end

Instance Attribute Details

#valueInteger

the current integer value that contains the bit fields

Returns:

  • (Integer)

    the current value of value



10
11
12
# File 'lib/bit_magic/bit_field.rb', line 10

def value
  @value
end

Instance Method Details

#read_bits(*args) ⇒ Hash

Read the specified bit indices into a hash with bit index as key

Examples:

Read a list of bits into a hash

bit_field = BitField.new(5)
bit_field.read_bits(0, 1, 2)
#=> {0=>1, 1=>0, 2=>1}
# because 5 is 101 in binary

Parameters:

  • bits (Integer)

    one or more bit indices to read.

Returns:

  • (Hash)

    a hash with the bit index as key and bit (1 or 0) as value



35
36
37
38
39
# File 'lib/bit_magic/bit_field.rb', line 35

def read_bits(*args)
  {}.tap do |m|
    args.each { |bit| m[bit] = @value[bit] }
  end
end

#read_field(*args) ⇒ Integer Also known as: []

Read the specified bit indices as a group, in the order given

Examples:

Read bits or a list of bits into an integer

bit_field = BitField.new(101) # 1100101 in binary, lsb on the right
bit_field.read_field(0, 1, 2) #=> 5 # or 101
bit_field.read_field(0) #= 1
bit_field.read_field( (2..6).to_a ) #=> 25 # or 11001

Parameters:

  • bits (Integer)

    one or more bit indices to read. Order matters!

Returns:

  • (Integer)

    the value of the bits read together into an integer



52
53
54
55
56
57
58
59
60
# File 'lib/bit_magic/bit_field.rb', line 52

def read_field(*args)
  m = 0
  args.flatten.each_with_index do |bit, i|
    if bit.is_a?(Integer)
      m |= ((@value[bit] || 0) << i)
    end
  end
  m
end

#write_bits(bit_values = {}) ⇒ Integer

Write to the specified bits, changing the internal @value to the new value

Examples:

Write new bit withs with their corresponding values

bit_field = BitField.new
bit_field.write_bits(0 => true) #=> 1
bit_field.write_bits(1 => true, 4 => true) #=> 19 # 10011
bit_field.write_bits(0 => false, 4 => false) #=> 2 # 10

Parameters:

  • bit_values (Hash) (defaults to: {})

    a hash with the key being a bit index and value being the value (must be 1, 0, true or false)

Returns:

  • (Integer)

    the value after writing the new bits their new values



76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/bit_magic/bit_field.rb', line 76

def write_bits(bit_values = {})
  bit_values.each_pair do |index, val|
    
    if !index.is_a?(Integer)
      raise InputError.new("BitField#write can only access bits by their index, #{index.inspect} is not a valid index")
    end
    
    if index < 0
      raise InputError.new("BitField#write can not write to negative indices")
    end
    
    if !(val === true) and !(val === false) and !(val === 1) and !(val === 0)
      raise InputError.new("BitField#write must have a boolean value, #{val.inspect} is not a boolean")
    end
    
    if val === true or val === 1
      @value |= (1 << index)
    else
      @value &= ~(1 << index)
    end
  
  end
  
  @value
end