Module: CRC::Calcurator

Defined in:
lib/crc/acrc.rb,
lib/crc/_file.rb,
lib/crc/_magic.rb,
lib/crc/_shift.rb,
lib/crc/_byruby.rb,
lib/crc.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#bitmaskObject (readonly)

Returns the value of attribute bitmask.



258
259
260
# File 'lib/crc/_byruby.rb', line 258

def bitmask
  @bitmask
end

#bitsizeObject (readonly)

Returns the value of attribute bitsize.



258
259
260
# File 'lib/crc/_byruby.rb', line 258

def bitsize
  @bitsize
end

#initial_crcObject (readonly)

Returns the value of attribute initial_crc.



258
259
260
# File 'lib/crc/_byruby.rb', line 258

def initial_crc
  @initial_crc
end

#nameObject (readonly)

Returns the value of attribute name.



258
259
260
# File 'lib/crc/_byruby.rb', line 258

def name
  @name
end

#polynomialObject (readonly)

Returns the value of attribute polynomial.



258
259
260
# File 'lib/crc/_byruby.rb', line 258

def polynomial
  @polynomial
end

#reflect_inputObject (readonly) Also known as: reflect_input?

Returns the value of attribute reflect_input.



258
259
260
# File 'lib/crc/_byruby.rb', line 258

def reflect_input
  @reflect_input
end

#reflect_outputObject (readonly) Also known as: reflect_output?

Returns the value of attribute reflect_output.



258
259
260
# File 'lib/crc/_byruby.rb', line 258

def reflect_output
  @reflect_output
end

#xor_outputObject (readonly)

Returns the value of attribute xor_output.



258
259
260
# File 'lib/crc/_byruby.rb', line 258

def xor_output
  @xor_output
end

Instance Method Details

#[](seq, *args) ⇒ Object



55
56
57
58
59
# 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) ⇒ Object

call-seq:

acrc(pre, post = nil, targetcrc = 0) -> byte string as arc-code

目的となる 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>
    


38
39
40
41
42
43
44
45
46
47
48
# 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(*args) ⇒ Object

call-seq:

combine(crc1, crc2) -> new combined crc
combine(crc1_int, crc2_int, crc2_len) -> new combined crc


96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# 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) ⇒ Object



75
76
77
# File 'lib/crc.rb', line 75

def crc(seq, crc = nil)
  finish(update(seq, setup(crc)))
end

#digest(seq, crc = nil) ⇒ Object



79
80
81
# File 'lib/crc.rb', line 79

def digest(seq, crc = nil)
  Aux.digest(crc(seq, crc), bitsize)
end

#file(path, *args) ⇒ Object



11
12
13
# File 'lib/crc/_file.rb', line 11

def file(path, *args)
  new(*args).file(path)
end

#finish(state) ⇒ Object



70
71
72
73
# 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) ⇒ Object



83
84
85
# File 'lib/crc.rb', line 83

def hexdigest(seq, crc = nil)
  Aux.hexdigest(crc(seq, crc), bitsize)
end

#inspectObject



144
145
146
# File 'lib/crc.rb', line 144

def inspect
  "#{super}{#{to_str}}"
end

#magicObject



70
71
72
73
74
# 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) ⇒ Object



76
77
78
# File 'lib/crc/_magic.rb', line 76

def magicdigest(seq, crc = nil)
  crc(seq, crc).to_magicdigest_for(self)
end

#magicnumberObject



64
65
66
67
68
# 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) ⇒ Object



148
149
150
# File 'lib/crc.rb', line 148

def pretty_inspect(q)
  q.text inspect
end

#setup(crc = nil) ⇒ Object Also known as: init



61
62
63
64
65
66
# 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

#shiftbits_by_bitbybit(bitset, state) ⇒ Object Also known as: shiftbits

call-seq:

shiftbits_by_bitbybit(bitset, state) -> state


7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# File 'lib/crc/_shift.rb', line 7

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

#shiftbytes_by_bitbybit(byteset, state) ⇒ Object Also known as: shiftbytes

call-seq:

shiftbytes_by_bitbybit(byteset, state)

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



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/crc/_shift.rb', line 36

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

#to_magicdigest(crc) ⇒ Object

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

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



85
86
87
# File 'lib/crc/_magic.rb', line 85

def to_magicdigest(crc)
  crc.to_magicdigest_for(self)
end

#to_strObject



112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# 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_tableObject



135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
# File 'lib/crc/_shift.rb', line 135

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

#unshiftbits_by_bitbybit(bitset, state) ⇒ Object Also known as: unshiftbits

call-seq:

unshiftbits_by_bitbybit(bitset, state)

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



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/crc/_shift.rb', line 67

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

#unshiftbytes_by_bitbybit(byteset, state) ⇒ Object

call-seq:

unshiftbytes_by_bitbybit(byteset, state)

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



103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# File 'lib/crc/_shift.rb', line 103

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) ⇒ Object Also known as: unshiftbytes



163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
# File 'lib/crc/_shift.rb', line 163

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

#variant?(obj) ⇒ Boolean

Returns:

  • (Boolean)


87
88
89
# File 'lib/crc.rb', line 87

def variant?(obj)
  obj.variant_for?(self)
end