Class: AMT::Utility::BitStruct

Inherits:
Object
  • Object
show all
Defined in:
lib/amt/utility/bit_struct.rb

Overview

A very simple base class which can be used to extract information from a number based on its bits, or to set it.

It isn’t useful to create objects directly from this class but one should create a subclass and use the provided class methods to define how to interpret the bits of a number.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(value = 0) ⇒ BitStruct

Create a new object. If value is an integer, it is used directly and interpreted bit-wise. If value is an array, it is processed in the following way:

  • symbols are interpreted as boolean fields

  • two-item arrays where the first item is a symbol and the second an integer are interpreted as unsigned or enum fields (depending in which category the symbol falls).



120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/amt/utility/bit_struct.rb', line 120

def initialize(value = 0)
  if value.kind_of?(Integer)
    @value = value
  elsif value.kind_of?(Array)
    @value = 0
    value.each do |sym, val|
      if val.nil?
        send("#{sym}!")
      else
        send("#{sym}=", val)
      end
    end
  else
    raise ArgumentError, 'invalid argument type specified'
  end
end

Instance Attribute Details

#valueObject (readonly)

The integer value which should be interpreted bit-wise.



112
113
114
# File 'lib/amt/utility/bit_struct.rb', line 112

def value
  @value
end

Class Method Details

.boolean(index, name, desc = name.to_s) ⇒ Object

Interpret the bit with the index (starting from zero) as boolean flag named name (should be a Symbol). If the bit at the index is 1, the flag is interpreted as true. The optional parameter desc can be used to provide a textual representation of the true state.

This method also adds accessor methods for the property. For example, if the property is called amt_enabled, the created getter method is called #amt_enabled? and the setter method is called #amt_enabled!. Note the trailing question/exclamation marks.

Example usage:

boolean 5, :amt_enabled, 'AMT is enabled'


27
28
29
30
31
32
33
34
35
36
# File 'lib/amt/utility/bit_struct.rb', line 27

def self.boolean(index, name, desc = name.to_s)
  index = (0x1 << index)
  (@boolean ||= []) << [name, desc]
  define_method("#{name}?") do
    @value & index == index
  end
  define_method("#{name}!") do
    @value |= index
  end
end

.enum(bit_range, name, values, desc = name.to_s) ⇒ Object

Interpret the bits in the bit_range (starting from zero) as unsigned integer value of an enumeration called name (should be a Symbol).

The parameter values specifies the mapping from number to meaning (normally a String). The optional parameter desc can be used to provide a textual representation of the meaning of the enumeration.

This method also adds accessor methods for the property. For example, if the property is called version, the created getter method is called #version and the setter method is called #version=.

Example usage:

enum 0..1, :device_type, {0 => 'Foo', 1 => 'Bar', 2 => 'Baz', 3 => Quux'}


92
93
94
95
96
97
98
99
100
101
# File 'lib/amt/utility/bit_struct.rb', line 92

def self.enum(bit_range, name, values, desc = name.to_s)
  mask = (2**(bit_range.end - bit_range.begin + 1) - 1) << bit_range.begin
  (@enum ||= []) << [name, values, desc]
  define_method(name) do
    values[(@value & mask) >> bit_range.begin]
  end
  define_method("#{name}=") do |number|
    @value |= (number << bit_range.begin) & mask
  end
end

.fieldsObject

Return a hash of all defined fields for this class. The hash keys are :boolean for the boolean properties, :unsigned for the unsigned integer properties and :enum for the enumeration properties. The hash values are arrays with information (depending on the type of the field) about the fields.



107
108
109
# File 'lib/amt/utility/bit_struct.rb', line 107

def self.fields
  {:boolean => @boolean || [], :unsigned => @unsigned || [], :enum => @enum || []}
end

.mboolean(mask, name, desc = name.to_s) ⇒ Object

Same as BitStruct.boolean but mask defines a bit mask and the value is only true if all bits specified by the bit mask (ie. all bits that are 1 in the bit mask) are set.

Example usage:

mboolean 0b101, :amt_enabled, 'AMT is enabled'


45
46
47
48
49
50
51
52
53
# File 'lib/amt/utility/bit_struct.rb', line 45

def self.mboolean(mask, name, desc = name.to_s)
  (@boolean ||= []) << [name, desc]
  define_method("#{name}?") do
    @value & mask == mask
  end
  define_method("#{name}!") do
    @value |= mask
  end
end

.unsigned(bit_range, name, desc = name.to_s) ⇒ Object

Interpret the bits in the bit_range (starting from zero) as unsigned integer named name (should be a Symbol). The optional parameter desc can be used to provide a textual representation of the meaning of the value.

This method also adds accessor methods for the property. For example, if the property is called version, the created getter method is called #version and the setter method is called #version=.

Example usage:

unsigned 2..5, :version, 'The integer version of the AMT device'


67
68
69
70
71
72
73
74
75
76
# File 'lib/amt/utility/bit_struct.rb', line 67

def self.unsigned(bit_range, name, desc = name.to_s)
  mask = (2**(bit_range.end - bit_range.begin + 1) - 1) << bit_range.begin
  (@unsigned ||= []) << [name, desc]
  define_method(name) do
    (@value & mask) >> bit_range.begin
  end
  define_method("#{name}=") do |number|
    @value |= (number << bit_range.begin) & mask
  end
end

Instance Method Details

#inspectObject

:nodoc:



137
138
139
140
141
142
# File 'lib/amt/utility/bit_struct.rb', line 137

def inspect #:nodoc:
  bools = self.class.fields[:boolean].select {|n,d| send("#{n}?")}.collect {|n, d| n.to_s}
  unsigns = self.class.fields[:unsigned].collect {|n, d| "#{n}=#{send(n)}"}
  enum = self.class.fields[:enum].collect {|n, d| "#{n}=#{send(n)}"}
  "#<#{self.class.name} #{(bools + unsigns + enum).join(', ')}>"
end

#list(used_fields = [:boolean, :unsigned, :enum]) ⇒ Object

Return an array with textual representations for output purposes of the the fields specified by used_fields.



146
147
148
149
150
151
152
153
154
155
156
157
158
# File 'lib/amt/utility/bit_struct.rb', line 146

def list(used_fields = [:boolean, :unsigned, :enum])
  result = []
  if used_fields.include?(:boolean)
    result += self.class.fields[:boolean].select {|n,d| send("#{n}?")}.collect {|n,d| d}
  end
  if used_fields.include?(:unsigned)
    result += self.class.fields[:unsigned].collect {|n, d| "#{d}=#{send(n)}"}
  end
  if used_fields.include?(:enum)
    result += self.class.fields[:enum].collect {|n, d| "#{d}=#{send(n)}"}
  end
  result
end