Class: Digest::CRC

Inherits:
Class
  • Object
show all
Includes:
Instance
Defined in:
lib/digest/crc.rb

Overview

Base class for all CRC algorithms.

Direct Known Subclasses

CRC1, CRC15, CRC16, CRC24, CRC32, CRC5, CRC64, CRC8

Constant Summary collapse

INIT_CRC =

The initial value of the CRC checksum

0x00
XOR_MASK =

The XOR mask to apply to the resulting CRC checksum

0x00
WIDTH =

The bit width of the CRC checksum

0
REFLECT_INPUT =

Define true or false whether the input direction is bit reversed or not of the CRC checksum

nil
TABLE =

Default place holder CRC table

[].freeze

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeCRC

Initializes the CRC checksum.



85
86
87
88
89
90
91
92
93
# File 'lib/digest/crc.rb', line 85

def initialize
  @init_crc      = self.class.const_get(:INIT_CRC)
  @xor_mask      = self.class.const_get(:XOR_MASK)
  @width         = self.class.const_get(:WIDTH)
  @reflect_input = self.class.const_get(:REFLECT_INPUT)
  @table         = self.class.const_get(:TABLE)

  reset
end

Class Method Details

.checksum(data) ⇒ Integer

Calculates the CRC checksum.

Parameters:

  • data (String)

    The given data.

Returns:

  • (Integer)

    The CRC checksum.



35
36
37
38
39
40
# File 'lib/digest/crc.rb', line 35

def self.checksum(data)
  crc = self.new
  crc << data

  return crc.checksum
end

.implementation:c_ext, :pure

Determines whether the library is using the optimized C extensions implementation, or the pure-Ruby implementation.

Returns:

  • (:c_ext, :pure)

Since:

  • 0.7.0



74
75
76
77
78
79
80
# File 'lib/digest/crc.rb', line 74

def self.implementation
  if instance_method(:update).source_location.nil?
    :c_ext
  else
    :pure
  end
end

.pack(crc) ⇒ String

Packs the given CRC checksum.

Parameters:

  • crc (Integer)

    The raw CRC checksum.

Returns:

  • (String)

    The packed CRC checksum.



51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/digest/crc.rb', line 51

def self.pack(crc)
  unless (width = self::WIDTH) > 0
    raise(NotImplementedError, "#{self} is incompleted as CRC")
  end

  bitclass   = width + (-width & 0x07)
  byte_count = bitclass / 8

  crc &= ~(-1 << width)

  result = [crc].pack("Q>")
  result[0, result.bytesize - byte_count] = ""
  result
end

Instance Method Details

#<<(data) ⇒ Object

See Also:



176
177
178
179
# File 'lib/digest/crc.rb', line 176

def <<(data)
  update(data)
  return self
end

#block_length1

The input block length.

Returns:

  • (1)


100
101
102
# File 'lib/digest/crc.rb', line 100

def block_length
  1
end

#checksumInteger

The resulting CRC checksum.

Returns:

  • (Integer)

    The resulting CRC checksum.



197
198
199
# File 'lib/digest/crc.rb', line 197

def checksum
  @crc ^ @xor_mask
end

#digest_lengthInteger

The length of the digest.

Returns:

  • (Integer)

    The length in bytes.



110
111
112
# File 'lib/digest/crc.rb', line 110

def digest_length
  (@width / 8.0).ceil
end

#finishObject

Finishes the CRC checksum calculation.

See Also:



206
207
208
# File 'lib/digest/crc.rb', line 206

def finish
  self.class.pack(checksum)
end

#resetInteger

Resets the CRC checksum.

Returns:

  • (Integer)

    The default value of the CRC checksum.



187
188
189
# File 'lib/digest/crc.rb', line 187

def reset
  @crc = @init_crc
end

#update(data) ⇒ Object

Updates the CRC checksum with the given data.

Parameters:

  • data (String)

    The data to update the CRC checksum with.

Raises:

  • (NotImplementedError)

    If WIDTH, TABLE, or REFLECT_INPUT constants are not set properly.



123
124
125
126
127
128
129
130
131
132
133
134
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
162
163
164
165
166
167
168
169
170
171
# File 'lib/digest/crc.rb', line 123

def update(data)
  unless @width >= 1
    raise(NotImplementedError, "incompleted #{self.class} as CRC (expected WIDTH to be 1 or more)")
  end

  if @table.empty?
    raise(NotImplementedError, "incompleted #{self.class} as CRC (expected TABLE to be not empty)")
  end

  if @reflect_input.nil?
    raise(NotImplementedError, "incompleted #{self.class} as CRC (expected REFLECT_INPUT to be not nil)")
  end

  table = @table
  crc   = @crc

  if @reflect_input
    if @width > 8
      data.each_byte do |b|
        crc = table[b ^ (0xff & crc)] ^ (crc >> 8)
      end
    else
      data.each_byte do |b|
        # Omit (crc >> 8) since bits upper than the lower 8 bits are always 0
        crc = table[b ^ (0xff & crc)]
      end
    end
  else
    if @width > 8
      higher_bit_off = @width - 8
      remain_mask    = ~(-1 << higher_bit_off)

      data.each_byte do |b|
        crc = table[b ^ (0xff & (crc >> higher_bit_off))] ^ ((remain_mask & crc) << 8)
      end
    else
      padding = 8 - @width

      data.each_byte do |b|
        # Omit (crc << 8) since bits lower than the upper 8 bits are always 0
        crc = table[b ^ (0xff & (crc << padding))]
      end
    end
  end

  @crc = crc

  self
end