Last active
August 29, 2015 13:56
-
-
Save glucero/8910619 to your computer and use it in GitHub Desktop.
a helper class for experimenting with bit fields
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Field | |
Bit = Struct.new(:to_s, :to_i, :to_bool, :regex) do | |
alias to_str to_s | |
def ===(other) entries.any? { |entry| entry === other } end | |
end | |
False = Bit.new(?0, 0, false, /^[0nf]/i) | |
True = Bit.new(?1, 1, true, /^[1yt]/i) | |
def to_s; @field.dup end | |
def to_i; @field.to_i 2 end | |
def to_f; to_i.to_f end | |
def to_a(type = :int) | |
case type | |
when :str then @field.chars | |
when :int then @field.chars.map &:to_i | |
when :bool then @field.chars.map &True.method(:===) | |
end | |
end | |
def [](index, type = :int) | |
case type | |
when :str then @field[index] | |
when :int then @field[index].to_i | |
when :bool then True === @field[index] | |
end | |
end | |
def []=(index, value) | |
@field[index] = (True === value) ? True : False | |
end | |
def initialize(field = False, bits: 8) | |
set field, bits: bits | |
end | |
def set(field = @field, bits: @bits) | |
tap do | |
@bits = bits | |
@field = string(field) | |
end | |
end | |
attr_reader :bits | |
def bits=(value) set bits: value end | |
alias length bits | |
alias size bits | |
def min; 0 end | |
def empty?; self == min end | |
def empty!; set False end | |
alias clear empty! | |
def max; (1 << bits).pred end | |
def full?; self == max end | |
def fill!; set max end | |
def +@; Field.new +to_i end | |
def -@; Field.new -to_i end | |
def ~@; Field.new ~to_i end | |
def next; Field.new to_i.next end | |
def pred; Field.new to_i.pred end | |
def reverse; Field.new to_s.reverse end | |
def invert; set ~to_i end | |
def toggle(index) | |
set self ^ ( 1 << (bits.pred - index) ) | |
end | |
alias flip toggle | |
def inc; set to_i.next end | |
def dec; set to_i.pred end | |
%i(+ - * / % >> << & | ^).each do |operator| | |
define_method(operator) do |operand| | |
Field.new to_i.send( operator, integer(operand) ) | |
end | |
end | |
%i(> < >= <= == <=>).each do |operator| | |
define_method(operator) { |operand| to_i.send operator, integer(operand) } | |
end | |
def ===(mask) (self & mask) == mask end | |
# def apply(mask) set (to_i | mask.to_i) end | |
# def revert(mask) set (to_i ^ mask.to_i) end | |
private def string(value) | |
case value | |
when String then ("#{False.to_s * bits}#{value.to_i}")[-bits..-1] | |
when Numeric then ("%0#{bits + 3}b" % value)[-bits..-1] | |
when Array then string value.join | |
when Field then string value.to_s | |
else string False | |
end | |
end | |
private def integer(value) | |
case value | |
when String then value.to_i(2) | |
when Numeric then value | |
when Array then integer value.join | |
when Field then value.to_i | |
else integer False | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment