module CRC::Calculator

Attributes

bitmask[R]
bitsize[R]
initial_crc[R]
name[R]
polynomial[R]
reflect_input[R]
reflect_input?[R]
reflect_output[R]
reflect_output?[R]
xor_output[R]

Public Instance Methods

[](seq, *args) click to toggle source
# File lib/crc.rb, line 55
def [](seq, *args)
  c = new(*args)
  c.update(seq) if seq
  c
end
acrc(pre, post = nil, targetcrc = 0) → byte string as arc-code click to toggle source

目的となる crc になるように、指定された crc に続くバイト列を逆算します。

出力されるバイト列は、crc のビット数を表現できるバイト数となります。

  • crc32(“123456789????”) の結果が 0 となるような、???? の部分を逆算する

    seq = "123456789"
    arced_seq = CRC::CRC32.acrc(seq)
    p CRC::CRC32[seq + arced_seq] # => #<CRC::CRC32:00000000>
    
  • crc32(“123456789????ABCDEFG”) の結果が 0 となるような、???? の部分を逆算する

    seq1 = "123456789"
    seq2 = "ABCDEFG"
    seq = seq1 + CRC::CRC32.acrc(seq1, seq2) + seq2
    p CRC::CRC32[seq] # => #<CRC::CRC32:00000000>
    
  • crc32(“123456789????ABCDEFG”) の結果が 0x12345678 となるような、???? の部分を逆算する

    seq1 = "123456789"
    seq2 = "ABCDEFG"
    targetcrc = 0x12345678
    seq = seq1 + CRC::CRC32.acrc(seq1, seq2, targetcrc) + seq2
    p CRC::CRC32[seq] # => #<CRC::CRC32:12345678>
    
# File lib/crc/acrc.rb, line 38
def acrc(pre, post = nil, targetcrc = 0)
  pre = pre.convert_internal_state_for(self)
  laststate = targetcrc.convert_target_state_for(self)
  state = unshiftbytes(post, laststate)
  bytesize = (bitsize + 7) / 8
  pre <<= (bytesize * 8 - bitsize) unless reflect_input?
  bytes = pre.splitbytes("".b, bytesize, reflect_input?)
  state = unshiftbytes(bytes, state)
  state <<= (bytesize * 8 - bitsize) unless reflect_input?
  state.splitbytes("".b, bytesize, reflect_input?)
end
combine(crc1, crc2) → new combined crc click to toggle source
combine(crc1_int, crc2_int, crc2_len) → new combined crc
# File lib/crc.rb, line 96
def combine(*args)
  case args.size
  when 2
    unless args[0].kind_of?(CRC) && args[1].kind_of?(CRC)
      raise ArgumentError, "When given two arguments, both arguments are should be CRC instance"
    end

    crc1 + crc2
  when 3
    Aux.combine(Integer(args[0].to_i), Integer(args[1].to_i), Integer(args[2].to_i),
                bitsize, polynomial, initial_crc, reflect_input?, reflect_output?, xor_output)
  else
    raise ArgumentError, "wrong number of arguments (given #{args.size}, expect 2..3)"
  end
end
crc(seq, crc = nil) click to toggle source
# File lib/crc.rb, line 75
def crc(seq, crc = nil)
  finish(update(seq, setup(crc)))
end
digest(seq, crc = nil) click to toggle source
# File lib/crc.rb, line 79
def digest(seq, crc = nil)
  Aux.digest(crc(seq, crc), bitsize)
end
file(path, *args) click to toggle source
# File lib/crc/_file.rb, line 11
def file(path, *args)
  new(*args).file(path)
end
finish(state) click to toggle source
# File lib/crc.rb, line 70
def finish(state)
  state = CRC.bitreflect(state, bitsize) if reflect_input? ^ reflect_output?
  state ^ xor_output & bitmask
end
hexdigest(seq, crc = nil) click to toggle source
# File lib/crc.rb, line 83
def hexdigest(seq, crc = nil)
  Aux.hexdigest(crc(seq, crc), bitsize)
end
init(crc = nil)
Alias for: setup
inspect() click to toggle source
# File lib/crc.rb, line 144
def inspect
  "#{super}{#{to_str}}"
end
magic() click to toggle source
# File lib/crc/_magic.rb, line 70
def magic
  @magic = hexdigest(__cached_magic_code__).freeze
  singleton_class.class_eval { attr_reader :magic }
  @magic
end
magicdigest(seq, crc = nil) click to toggle source
# File lib/crc/_magic.rb, line 76
def magicdigest(seq, crc = nil)
  crc(seq, crc).to_magicdigest_for(self)
end
magicnumber() click to toggle source
# File lib/crc/_magic.rb, line 64
def magicnumber
  @magicnumber = crc(__cached_magic_code__)
  singleton_class.class_eval { attr_reader :magicnumber }
  @magicnumber
end
pretty_inspect(q) click to toggle source
# File lib/crc.rb, line 148
def pretty_inspect(q)
  q.text inspect
end
setup(crc = nil) click to toggle source
# File lib/crc.rb, line 61
def setup(crc = nil)
  crc ||= initial_crc
  crc ^= xor_output
  crc = CRC.bitreflect(crc, bitsize) if reflect_input? ^ reflect_output?
  crc & bitmask
end
Also aliased as: init
# File lib/crc/_shift.rb, line 11
def shiftbits_by_bitbybit(bitset, state)
  bitset = Array(bitset)

  if reflect_input?
    poly = CRC.bitreflect(polynomial, bitsize)
    bitset.each do |b|
      state ^= (1 & b)
      state = (state[0] == 0) ? (state >> 1) : ((state >> 1) ^ poly)
    end

    state
  else
    Aux.slide_to_head(bitsize, state, polynomial, bitmask) do |s, poly, csh, head, carries|
      bitset.each do |b|
        s ^= (1 & b) << head
        s = (s[head] == 0) ? (s << 1) : (((carries & s) << 1) ^ poly)
      end

      s
    end
  end
end
Also aliased as: shiftbits

standard input の場合は byte は上位ビットから、reflect input の場合は byte は下位ビットから計算されます。

# File lib/crc/_shift.rb, line 40
def shiftbytes_by_bitbybit(byteset, state)
  if reflect_input?
    poly = CRC.bitreflect(polynomial, bitsize)
    byteset.each_byte do |b|
      state ^= 0xff & b
      8.times do
        state = (state[0] == 0) ? (state >> 1) : ((state >> 1) ^ poly)
      end
    end

    state
  else
    Aux.slide_to_head(bitsize, state, polynomial, bitmask) do |s, poly, csh, head, carries|
      byteset.each_byte do |b|
        s ^= (0xff & b) << csh
        8.times do
          s = (s[head] == 0) ? (s << 1) : (((carries & s) << 1) ^ poly)
        end
      end

      s
    end
  end
end
Also aliased as: shiftbytes
to_magicdigest(crc) click to toggle source

crc 値を与えると magicdigest へと変換したバイナリデータを返します。

crc には整数値、digest/hexdigest データ、変種を含む CRC インスタンスを渡すことが出来ます。

# File lib/crc/_magic.rb, line 85
def to_magicdigest(crc)
  crc.to_magicdigest_for(self)
end
to_str() click to toggle source
# File lib/crc.rb, line 112
def to_str
  case
  when bitsize > 64 then width = 20
  when bitsize > 32 then width = 16
  when bitsize > 16 then width =  8
  when bitsize >  8 then width =  4
  else                   width =  2
  end

  if reflect_input?
    ref = " reflect-in#{reflect_output? ? "/out" : ""}"
  else
    ref = reflect_output? ? " reflect-out" : ""
  end

  case initial_crc
  when 0        then init = "0"
  when bitmask  then init = "~0"
  when 1        then init = "1"
  else               init = "0x%0#{width}X" % initial_crc
  end

  case xor_output
  when 0        then xor = "0"
  when bitmask  then xor = "~0"
  when 1        then xor = "1"
  else               xor = "0x%0#{width}X" % xor_output
  end

  "CRC-%d-0x%0#{width}X%s init=%s xor=%s" % [bitsize, polynomial, ref, init, xor]
end
unshift_table() click to toggle source
# File lib/crc/_shift.rb, line 139
def unshift_table
  if reflect_input?
    if bitsize < 8
      pad = 8 - bitsize
      shift = 0
    else
      pad = 0
      shift = bitsize - 8
    end
    poly = ((CRC.bitreflect(polynomial, bitsize) << 1) | 1) << pad
    head = bitsize + pad
    @unshift_table = 256.times.map do |ch|
      state = ch << shift
      8.times do |i|
        state <<= 1
        state ^= poly unless state[head] == 0
      end
      state >> pad
    end
  else
    raise NotImplementedError
  end

  singleton_class.module_eval { attr_reader :unshift_table }

  @unshift_table
end

bitset を与えることで state となるような内部状態を逆算します。

# File lib/crc/_shift.rb, line 71
def unshiftbits_by_bitbybit(bitset, state)
  bitset = Array(bitset)

  if reflect_input?
    poly = (CRC.bitreflect(polynomial, bitsize) << 1) | 1
    head = bitsize
    bitset.reverse_each do |b|
      state <<= 1
      state ^= poly unless state[head] == 0
      state ^= 1 & b
    end

    state
  else
    Aux.slide_to_head(bitsize, state, polynomial, bitmask) do |s, poly, csh, head, carries|
      headbit = 1 << head
      lowoff = (head + 1) - bitsize
      poly = (poly >> 1) | headbit
      bitset.reverse_each do |b|
        tmp = s[lowoff]
        s >>= 1
        s ^= poly unless tmp == 0
        s ^= (1 & b) << head
      end

      s
    end
  end
end
Also aliased as: unshiftbits
unshiftbytes(byteset, state)
unshiftbytes_by_bitbybit(byteset, state) click to toggle source

byteset を与えることで state となるような内部状態を逆算します。

# File lib/crc/_shift.rb, line 107
def unshiftbytes_by_bitbybit(byteset, state)
  if reflect_input?
    poly = (CRC.bitreflect(polynomial, bitsize) << 1) | 1
    head = bitsize
    byteset.reverse_each_byte do |b|
      7.downto(0) do |i|
        state <<= 1
        state ^= poly unless state[head] == 0
        state ^= b[i]
      end
    end

    state
  else
    Aux.slide_to_head(bitsize, state, polynomial, bitmask) do |s, poly, csh, head, carries|
      headbit = 1 << head
      lowoff = (head + 1) - bitsize
      poly = (poly >> 1) | headbit
      byteset.reverse_each_byte do |b|
        8.times do |i|
          tmp = s[lowoff]
          s >>= 1
          s ^= poly unless tmp == 0
          s ^= b[i] << head
        end
      end

      s
    end
  end
end
unshiftbytes_by_table(byteset, state) click to toggle source
# File lib/crc/_shift.rb, line 167
def unshiftbytes_by_table(byteset, state)
  if reflect_input?
    table = unshift_table
    if bitsize < 8
      pad = 8 - bitsize
      shift = 0
      mask = bitmask
      byteset.reverse_each_byte do |ch|
        state = (state << 8) ^ ch
        state = table[state >> bitsize] ^ (ch & mask)
      end
    else
      shift = bitsize - 8
      mask = ~(~0 << shift)
      byteset.reverse_each_byte do |ch|
        state = table[state >> shift] ^ ((state & mask) << 8)
        state ^= ch
      end
    end

    state
  else
    unshiftbytes_by_bitbybit(byteset, state)
  end
end
Also aliased as: unshiftbytes
variant?(obj) click to toggle source
# File lib/crc.rb, line 87
def variant?(obj)
  obj.variant_for?(self)
end