Ruby で each 実装

each ブロックの実装楽しい。

def each
  @data.each_byte {
    |byte|
    (0..7).each {
      |bit_offset|
      bit =  (byte >> (7 - bit_offset)) & 1
      yield(bit)
    }
  }
end

class に↑こう書いておくだけで、

$io.each {
  |b|
  printf("%d", b)
}

こんな風に 1 bit ずつ each で回せる。うーむw

ord の問題

ついでに、ord の問題も、 Rubyのバージョンで分岐させて 1.8 でも動くようにしてみた。

if RUBY_VERSION >= '1.9.0' # >_<;
  byte = @data[byte_offset].ord
else
  byte = @data[byte_offset]
end

2の補数

n bit 取るメソッドで、負の値を扱えるようにしてみた。

def get_bits_signed!(bit_width)
  bits = get_bits!(bit_width)
  sig_b = 1 << (bit_width - 1)
  if (sig_b & bits) # negaive
    bit_mask = (sig_b << 1) - 1
    bits = bits ^ bit_mask; # bit reverse
    bits = - (bits + 1)
  end
  bits
end

例えば、11bitなんだけど符号付きだよ。みたいな変態的なバイナリフォーマットを扱うときに必要。

補足 (2009/08/19)
  if (sig_b & bits) # negaive

↑これは間違い。↓こう直した。

  if ((sig_b & bits) != 0) # negaive