CRC-32【代碼實現】

C

#include <inttypes.h>
#include <stdio.h>
#include <string.h>
 
uint32_t
rc_crc32(uint32_t crc, const char *buf, size_t len)
{
	static uint32_t table[256];
	static int have_table = 0;
	uint32_t rem;
	uint8_t octet;
	int i, j;
	const char *p, *q;
 
	/* This check is not thread safe; there is no mutex. */
	if (have_table == 0) {
		/* Calculate CRC table. */
		for (i = 0; i < 256; i++) {
			rem = i;  /* remainder from polynomial division */
			for (j = 0; j < 8; j++) {
				if (rem & 1) {
					rem >>= 1;
					rem ^= 0xedb88320;
				} else
					rem >>= 1;
			}
			table[i] = rem;
		}
		have_table = 1;
	}
 
	crc = ~crc;
	q = buf + len;
	for (p = buf; p < q; p++) {
		octet = *p;  /* Cast to unsigned octet. */
		crc = (crc >> 8) ^ table[(crc & 0xff) ^ octet];
	}
	return ~crc;
}
 
int
main()
{
	const char *s = "The quick brown fox jumps over the lazy dog";
	printf("%" PRIX32 "\n", rc_crc32(0, s, strlen(s)));
 
	return 0;
}

C++

#include <algorithm>
#include <array>
#include <cstdint>
#include <numeric>
 
// These headers are only needed for main(), to demonstrate.
#include <iomanip>
#include <iostream>
#include <string>
 
// Generates a lookup table for the checksums of all 8-bit values.
std::array<std::uint_fast32_t, 256> generate_crc_lookup_table() noexcept
{
  auto const reversed_polynomial = std::uint_fast32_t{0xEDB88320uL};
 
  // This is a function object that calculates the checksum for a value,
  // then increments the value, starting from zero.
  struct byte_checksum
  {
    std::uint_fast32_t operator()() noexcept
    {
      auto checksum = static_cast<std::uint_fast32_t>(n++);
 
      for (auto i = 0; i < 8; ++i)
        checksum = (checksum >> 1) ^ ((checksum & 0x1u) ? reversed_polynomial : 0);
 
      return checksum;
    }
 
    unsigned n = 0;
  };
 
  auto table = std::array<std::uint_fast32_t, 256>{};
  std::generate(table.begin(), table.end(), byte_checksum{});
 
  return table;
}
 
// Calculates the CRC for any sequence of values. (You could use type traits and a
// static assert to ensure the values can be converted to 8 bits.)
template <typename InputIterator>
std::uint_fast32_t crc(InputIterator first, InputIterator last)
{
  // Generate lookup table only on first use then cache it - this is thread-safe.
  static auto const table = generate_crc_lookup_table();
 
  // Calculate the checksum - make sure to clip to 32 bits, for systems that don't
  // have a true (fast) 32-bit type.
  return std::uint_fast32_t{0xFFFFFFFFuL} &
    ~std::accumulate(first, last,
      ~std::uint_fast32_t{0} & std::uint_fast32_t{0xFFFFFFFFuL},
        [](std::uint_fast32_t checksum, std::uint_fast8_t value) 
          { return table[(checksum ^ value) & 0xFFu] ^ (checksum >> 8); });
}
 
int main()
{
  auto const s = std::string{"The quick brown fox jumps over the lazy dog"};
 
  std::cout << std::hex << std::setw(8) << std::setfill('0') << crc(s.begin(), s.end()) << '\n';
}

C#

/// <summary>
    /// Performs 32-bit reversed cyclic redundancy checks.
    /// </summary>
    public class Crc32
    {
        #region Constants
        /// <summary>
        /// Generator polynomial (modulo 2) for the reversed CRC32 algorithm. 
        /// </summary>
        private const UInt32 s_generator = 0xEDB88320;
        #endregion
 
        #region Constructors
        /// <summary>
        /// Creates a new instance of the Crc32 class.
        /// </summary>
        public Crc32()
        {
            // Constructs the checksum lookup table. Used to optimize the checksum.
            m_checksumTable = Enumerable.Range(0, 256).Select(i =>
            {
                var tableEntry = (uint)i;
                for (var j = 0; j < 8; ++j)
                {
                    tableEntry = ((tableEntry & 1) != 0)
                        ? (s_generator ^ (tableEntry >> 1)) 
                        : (tableEntry >> 1);
                }
                return tableEntry;
            }).ToArray();
        }
        #endregion
 
        #region Methods
        /// <summary>
        /// Calculates the checksum of the byte stream.
        /// </summary>
        /// <param name="byteStream">The byte stream to calculate the checksum for.</param>
        /// <returns>A 32-bit reversed checksum.</returns>
        public UInt32 Get<T>(IEnumerable<T> byteStream)
        {
            try
            {
                // Initialize checksumRegister to 0xFFFFFFFF and calculate the checksum.
                return ~byteStream.Aggregate(0xFFFFFFFF, (checksumRegister, currentByte) => 
                          (m_checksumTable[(checksumRegister & 0xFF) ^ Convert.ToByte(currentByte)] ^ (checksumRegister >> 8)));
            }
            catch (FormatException e)
            {
                throw new CrcException("Could not read the stream out as bytes.", e);
            }
            catch (InvalidCastException e)
            {
                throw new CrcException("Could not read the stream out as bytes.", e);
            }
            catch (OverflowException e)
            {
                throw new CrcException("Could not read the stream out as bytes.", e);
            }
        }
        #endregion
 
        #region Fields
        /// <summary>
        /// Contains a cache of calculated checksum chunks.
        /// </summary>
        private readonly UInt32[] m_checksumTable;
 
        #endregion
    }

Go

package main
 
import "fmt"
 
var table [256]uint32
 
func init() {
    for i := range table {
        word := uint32(i)
        for j := 0; j < 8; j++ {
            if word&1 == 1 {
                word = (word >> 1) ^ 0xedb88320
            } else {
                word >>= 1
            }
        }
        table[i] = word
    }
}
 
func crc32(s string) uint32 {
    crc := ^uint32(0)
    for i := 0; i < len(s); i++ {
        crc = table[byte(crc)^s[i]] ^ (crc >> 8)
    }
    return ^crc
}
 
func main() {
    fmt.Printf("%0x\n", crc32("The quick brown fox jumps over the lazy dog"))
}

Java

import java.util.zip.* ;
 
public class CRCMaker {
   public static void main( String[ ] args ) {
      String toBeEncoded = new String( "The quick brown fox jumps over the lazy dog" ) ;
      CRC32 myCRC = new CRC32( ) ;
      myCRC.update( toBeEncoded.getBytes( ) ) ;
      System.out.println( "The CRC-32 value is : " + Long.toHexString( myCRC.getValue( ) ) + " !" ) ;
   }
}

JavaScript

(() => {
    'use strict';
 
    const main = () =>
        showHex(
            crc32('The quick brown fox jumps over the lazy dog')
        );
 
    // crc32 :: String -> Int
    const crc32 = str => {
 
        // table :: [Int]
        const table = map(
            n => take(9,
                iterate(
                    x => (
                        x & 1 ? z => 0xEDB88320 ^ z : id
                    )(x >>> 1),
                    n
                )
            )[8],
            enumFromTo(0, 255)
        );
        return (
            foldl(
                (a, c) => (a >>> 8) ^ table[
                    (a ^ c.charCodeAt(0)) & 255
                ],
                -1,
                chars(str)
            ) ^ -1
        );
    };
 
    // GENERIC ABSTRACTIONS -------------------------------
 
    // chars :: String -> [Char]
    const chars = s => s.split('');
 
    // enumFromTo :: Int -> Int -> [Int]
    const enumFromTo = (m, n) =>
        Array.from({
            length: 1 + n - m
        }, (_, i) => m + i);
 
    // foldl :: (a -> b -> a) -> a -> [b] -> a
    const foldl = (f, a, xs) => xs.reduce(f, a);
 
    // id :: a -> a
    const id = x => x;
 
    // iterate :: (a -> a) -> a -> Gen [a]
    function* iterate(f, x) {
        let v = x;
        while (true) {
            yield(v);
            v = f(v);
        }
    }
 
    // map :: (a -> b) -> [a] -> [b]
    const map = (f, xs) => xs.map(f);
 
    // showHex :: Int -> String
    const showHex = n =>
        n.toString(16);
 
    // take :: Int -> [a] -> [a]
    // take :: Int -> String -> String
    const take = (n, xs) =>
        xs.constructor.constructor.name !== 'GeneratorFunction' ? (
            xs.slice(0, n)
        ) : [].concat.apply([], Array.from({
            length: n
        }, () => {
            const x = xs.next();
            return x.done ? [] : [x.value];
        }));
 
 
    // MAIN -------------
    const result = main();
    return (
        console.log(result),
        result
    );
})();

Kotlin

// version 1.0.6
 
import java.util.zip.CRC32
 
fun main(args: Array<String>) {
    val text = "The quick brown fox jumps over the lazy dog"
    val crc = CRC32()
    with (crc) {
        update(text.toByteArray())
        println("The CRC-32 checksum of '$text' = ${"%x".format(value)}")
    }
}

Python

def create_table():
    a = []
    for i in range(256):
        k = i
        for j in range(8):
            if k & 1:
                k ^= 0x1db710640
            k >>= 1
        a.append(k)
    return a
 
def crc_update(buf, crc):
    crc ^= 0xffffffff
    for k in buf:
        crc = (crc >> 8) ^ crc_table[(crc & 0xff) ^ k]
    return crc ^ 0xffffffff
 
crc_table = create_table()
print(hex(crc_update(b"The quick brown fox jumps over the lazy dog", 0)))
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章