博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
CRC 自动判断大端 小端
阅读量:6161 次
发布时间:2019-06-21

本文共 8977 字,大约阅读时间需要 29 分钟。

 

/* aos_crc64.c -- compute CRC-64 * Copyright (C) 2013 Mark Adler * Version 1.4  16 Dec 2013  Mark Adler *//*  This software is provided 'as-is', without any express or implied  warranty.  In no event will the author be held liable for any damages  arising from the use of this software.  Permission is granted to anyone to use this software for any purpose,  including commercial applications, and to alter it and redistribute it  freely, subject to the following restrictions:  1. The origin of this software must not be misrepresented; you must not     claim that you wrote the original software. If you use this software     in a product, an acknowledgment in the product documentation would be     appreciated but is not required.  2. Altered source versions must be plainly marked as such, and must not be     misrepresented as being the original software.  3. This notice may not be removed or altered from any source distribution.  Mark Adler  madler@alumni.caltech.edu *//* Compute CRC-64 in the manner of xz, using the ECMA-182 polynomial,   bit-reversed, with one's complement pre and post processing.  Provide a   means to combine separately computed CRC-64's. *//* Version history:   1.0  13 Dec 2013  First version   1.1  13 Dec 2013  Fix comments in test code   1.2  14 Dec 2013  Determine endianess at run time   1.3  15 Dec 2013  Add eight-byte processing for big endian as well                     Make use of the pthread library optional   1.4  16 Dec 2013  Make once variable volatile for limited thread protection */#include "aos_crc64.h"/* 64-bit CRC polynomial with these coefficients, but reversed:    64, 62, 57, 55, 54, 53, 52, 47, 46, 45, 40, 39, 38, 37, 35, 33, 32,    31, 29, 27, 24, 23, 22, 21, 19, 17, 13, 12, 10, 9, 7, 4, 1, 0 */#define POLY UINT64_C(0xc96c5795d7870f42)/* Tables for CRC calculation -- filled in by initialization functions that are   called once.  These could be replaced by constant tables generated in the   same way.  There are two tables, one for each endianess.  Since these are   static, i.e. local, one should be compiled out of existence if the compiler   can evaluate the endianess check in crc64() at compile time. */static uint64_t crc64_little_table[8][256];static uint64_t crc64_big_table[8][256];/* Fill in the CRC-64 constants table. */static void crc64_init(uint64_t table[][256]){    unsigned n, k;    uint64_t crc;    /* generate CRC-64's for all single byte sequences */    for (n = 0; n < 256; n++) {        crc = n;        for (k = 0; k < 8; k++)            crc = crc & 1 ? POLY ^ (crc >> 1) : crc >> 1;        table[0][n] = crc;    }    /* generate CRC-64's for those followed by 1 to 7 zeros */    for (n = 0; n < 256; n++) {        crc = table[0][n];        for (k = 1; k < 8; k++) {            crc = table[0][crc & 0xff] ^ (crc >> 8);            table[k][n] = crc;        }    }}/* This function is called once to initialize the CRC-64 table for use on a   little-endian architecture. */static void crc64_little_init(void){    crc64_init(crc64_little_table);}/* Reverse the bytes in a 64-bit word. */static APR_INLINE uint64_t rev8(uint64_t a){    uint64_t m;    m = UINT64_C(0xff00ff00ff00ff);    a = ((a >> 8) & m) | (a & m) << 8;    m = UINT64_C(0xffff0000ffff);    a = ((a >> 16) & m) | (a & m) << 16;    return a >> 32 | a << 32;}/* This function is called once to initialize the CRC-64 table for use on a   big-endian architecture. */static void crc64_big_init(void){    unsigned k, n;    crc64_init(crc64_big_table);    for (k = 0; k < 8; k++)        for (n = 0; n < 256; n++)            crc64_big_table[k][n] = rev8(crc64_big_table[k][n]);}/* Run the init() function exactly once.  If pthread.h is not included, then   this macro will use a simple static state variable for the purpose, which is   not thread-safe.  The init function must be of the type void init(void). */#ifdef PTHREAD_ONCE_INIT#  define ONCE(init) \    do { \        static pthread_once_t once = PTHREAD_ONCE_INIT; \        pthread_once(&once, init); \    } while (0)#else#  define ONCE(init) \    do { \        static volatile int once = 1; \        if (once) { \            if (once++ == 1) { \                init(); \                once = 0; \            } \            else \                while (once) \                    ; \        } \    } while (0)#endif/* Calculate a CRC-64 eight bytes at a time on a little-endian architecture. */static APR_INLINE uint64_t crc64_little(uint64_t crc, void *buf, size_t len){    unsigned char *next = buf;    ONCE(crc64_little_init);    crc = ~crc;    while (len && ((uintptr_t)next & 7) != 0) {        crc = crc64_little_table[0][(crc ^ *next++) & 0xff] ^ (crc >> 8);        len--;    }    while (len >= 8) {        crc ^= *(uint64_t *)next;        crc = crc64_little_table[7][crc & 0xff] ^              crc64_little_table[6][(crc >> 8) & 0xff] ^              crc64_little_table[5][(crc >> 16) & 0xff] ^              crc64_little_table[4][(crc >> 24) & 0xff] ^              crc64_little_table[3][(crc >> 32) & 0xff] ^              crc64_little_table[2][(crc >> 40) & 0xff] ^              crc64_little_table[1][(crc >> 48) & 0xff] ^              crc64_little_table[0][crc >> 56];        next += 8;        len -= 8;    }    while (len) {        crc = crc64_little_table[0][(crc ^ *next++) & 0xff] ^ (crc >> 8);        len--;    }    return ~crc;}/* Calculate a CRC-64 eight bytes at a time on a big-endian architecture. */static APR_INLINE uint64_t crc64_big(uint64_t crc, void *buf, size_t len){    unsigned char *next = buf;    ONCE(crc64_big_init);    crc = ~rev8(crc);    while (len && ((uintptr_t)next & 7) != 0) {        crc = crc64_big_table[0][(crc >> 56) ^ *next++] ^ (crc << 8);        len--;    }    while (len >= 8) {        crc ^= *(uint64_t *)next;        crc = crc64_big_table[0][crc & 0xff] ^              crc64_big_table[1][(crc >> 8) & 0xff] ^              crc64_big_table[2][(crc >> 16) & 0xff] ^              crc64_big_table[3][(crc >> 24) & 0xff] ^              crc64_big_table[4][(crc >> 32) & 0xff] ^              crc64_big_table[5][(crc >> 40) & 0xff] ^              crc64_big_table[6][(crc >> 48) & 0xff] ^              crc64_big_table[7][crc >> 56];        next += 8;        len -= 8;    }    while (len) {        crc = crc64_big_table[0][(crc >> 56) ^ *next++] ^ (crc << 8);        len--;    }    return ~rev8(crc);}/* Return the CRC-64 of buf[0..len-1] with initial crc, processing eight bytes   at a time.  This selects one of two routines depending on the endianess of   the architecture.  A good optimizing compiler will determine the endianess   at compile time if it can, and get rid of the unused code and table.  If the   endianess can be changed at run time, then this code will handle that as   well, initializing and using two tables, if called upon to do so. */uint64_t aos_crc64(uint64_t crc, void *buf, size_t len){    uint64_t n = 1;    return *(char *)&n ? crc64_little(crc, buf, len) :                         crc64_big(crc, buf, len);}#define GF2_DIM 64      /* dimension of GF(2) vectors (length of CRC) */static uint64_t gf2_matrix_times(uint64_t *mat, uint64_t vec){    uint64_t sum;    sum = 0;    while (vec) {        if (vec & 1)            sum ^= *mat;        vec >>= 1;        mat++;    }    return sum;}static void gf2_matrix_square(uint64_t *square, uint64_t *mat){    unsigned n;    for (n = 0; n < GF2_DIM; n++)        square[n] = gf2_matrix_times(mat, mat[n]);}/* Return the CRC-64 of two sequential blocks, where crc1 is the CRC-64 of the   first block, crc2 is the CRC-64 of the second block, and len2 is the length   of the second block. */uint64_t aos_crc64_combine(uint64_t crc1, uint64_t crc2, uintmax_t len2){    unsigned n;    uint64_t row;    uint64_t even[GF2_DIM];     /* even-power-of-two zeros operator */    uint64_t odd[GF2_DIM];      /* odd-power-of-two zeros operator */    /* degenerate case */    if (len2 == 0)        return crc1;    /* put operator for one zero bit in odd */    odd[0] = POLY;              /* CRC-64 polynomial */    row = 1;    for (n = 1; n < GF2_DIM; n++) {        odd[n] = row;        row <<= 1;    }    /* put operator for two zero bits in even */    gf2_matrix_square(even, odd);    /* put operator for four zero bits in odd */    gf2_matrix_square(odd, even);    /* apply len2 zeros to crc1 (first square will put the operator for one       zero byte, eight zero bits, in even) */    do {        /* apply zeros operator for this bit of len2 */        gf2_matrix_square(even, odd);        if (len2 & 1)            crc1 = gf2_matrix_times(even, crc1);        len2 >>= 1;        /* if no more bits set, then done */        if (len2 == 0)            break;        /* another iteration of the loop with odd and even swapped */        gf2_matrix_square(odd, even);        if (len2 & 1)            crc1 = gf2_matrix_times(odd, crc1);        len2 >>= 1;        /* if no more bits set, then done */    } while (len2 != 0);    /* return combined crc */    crc1 ^= crc2;    return crc1;}

 

转载地址:http://mtafa.baihongyu.com/

你可能感兴趣的文章
汉字转拼音 (转)
查看>>
会计基础_001
查看>>
小程序: 查看正在写的页面
查看>>
Jenkins持续集成环境部署
查看>>
MWeb 1.4 新功能介绍二:静态博客功能增强
查看>>
预处理、const与sizeof相关面试题
查看>>
爬虫豆瓣top250项目-开发文档
查看>>
有趣的数学书籍
查看>>
teamviewer 卸载干净
查看>>
eclipse的maven、Scala环境搭建
查看>>
架构师之路(一)- 什么是软件架构
查看>>
USACO 土地购买
查看>>
【原创】远景能源面试--一面
查看>>
B1010.一元多项式求导(25)
查看>>
10、程序员和编译器之间的关系
查看>>
配置 RAILS FOR JRUBY1.7.4
查看>>
AndroidStudio中导入SlidingMenu报错解决方案
查看>>
修改GRUB2背景图片
查看>>
Ajax异步
查看>>
好记性不如烂笔杆-android学习笔记<十六> switcher和gallery
查看>>