169 lines
5.3 KiB
C++
169 lines
5.3 KiB
C++
/**
|
||
* @file Crc.hpp
|
||
*
|
||
* @date Created on: 30 нояб. 2018 г.
|
||
* @author АО ДИАКОНТ
|
||
* - maksimenko
|
||
* @revision
|
||
* v1.0 - 6.12.2018
|
||
*/
|
||
|
||
#ifndef SOURCE_COMMON_CRC_HPP_
|
||
#define SOURCE_COMMON_CRC_HPP_
|
||
|
||
#include <cstddef>
|
||
#include <stdint.h>
|
||
|
||
namespace common {
|
||
namespace crc {
|
||
|
||
/**
|
||
* @brief Менеджер таблицы расчета контрольной суммы
|
||
* @param Param тип описывающий алгоритм подсчета (см. CrcDesc.hpp)
|
||
* @detailed Ведет подсчет ссылок на объекты хранения контрольной суммы для
|
||
* обеспечивая выденленным на куче таблицей расчета CRC. Удаляем таблицу
|
||
* при уничтожении всех объекты хранения контрольной суммы.
|
||
*/
|
||
template <typename Param>
|
||
class CrcTable {
|
||
|
||
typedef typename Param::res_t res_t;
|
||
|
||
res_t * mCrcTbl;
|
||
uint16_t mcRef;
|
||
|
||
public:
|
||
static CrcTable & Instance();
|
||
res_t operator[](int i) { return mCrcTbl[i]; }
|
||
CrcTable & operator++() { mcRef++; if ( !mCrcTbl )alloc (); return *this; }
|
||
CrcTable & operator--() { if ( !--mcRef )free (); return *this; }
|
||
|
||
void inititialize() {
|
||
alloc();
|
||
}
|
||
|
||
private:
|
||
CrcTable() : mCrcTbl(NULL), mcRef(1) {}
|
||
CrcTable(const CrcTable &);
|
||
CrcTable & operator=(const CrcTable &);
|
||
|
||
void alloc() {
|
||
static res_t crc_table[256];
|
||
mCrcTbl = crc_table;
|
||
|
||
for ( uint32_t i = 0; i < 256; i++ ) {
|
||
uint32_t v = Param::reflect ? i: i << (Param::width_bit-8);
|
||
for ( uint16_t j = 0; j < 8; j++ ) {
|
||
v = Param::reflect ?
|
||
v & (1UL<<(0 )) ? (v>>1) ^ Param::poly : (v>>1) :
|
||
v & (1UL<<(Param::width_bit-1)) ? (v<<1) ^ Param::poly : (v<<1);
|
||
}
|
||
mCrcTbl[i] = v & ~0UL>>(32-Param::width_bit);
|
||
}
|
||
}
|
||
void free() {
|
||
//mCrcTbl = NULL;
|
||
}
|
||
};
|
||
|
||
template <typename Param>
|
||
CrcTable<Param>& CrcTable<Param>::Instance() {
|
||
static CrcTable mObj;
|
||
return mObj;
|
||
}
|
||
|
||
/**
|
||
* @brief Хранилище значения контрольной суммы
|
||
* @detailed Взаимодействует c CrcTable<Param> обеспечивая доступ к таблице
|
||
* для расчета CRC. Обеспечивает начальный и конечный этап получения
|
||
* контрольной суммы. Реализует операторы приведения типа возвращающий
|
||
* конечную стадию (XOR) вычисления CRC.
|
||
*/
|
||
template <typename Param>
|
||
class CrcVal {
|
||
|
||
typedef typename Param::res_t res_t;
|
||
|
||
res_t mCrc;
|
||
|
||
public:
|
||
CrcTable<Param> & mCrcTbl;
|
||
|
||
public:
|
||
CrcVal () : mCrc(Param::init), mCrcTbl(CrcTable<Param>::Instance()) {
|
||
++mCrcTbl;
|
||
}
|
||
CrcVal & operator=(const CrcVal & obj) {
|
||
mCrc = obj.mCrc;
|
||
return *this;
|
||
}
|
||
|
||
CrcVal( const CrcVal & obj ) : mCrcTbl(CrcTable<Param>::Instance()) {
|
||
mCrc = obj.mCrc;
|
||
++mCrcTbl;
|
||
}
|
||
|
||
operator uint32_t() const {
|
||
return mCrc & ~0UL>>(32-Param::width_bit) ^ Param::final;
|
||
}
|
||
operator uint16_t () const {
|
||
return (uint32_t)mCrc;
|
||
}
|
||
#ifdef __GNUG__
|
||
operator uint8_t () const { return (uint32_t)mCrc; }
|
||
#endif
|
||
|
||
res_t & value() const {
|
||
return const_cast<res_t &>(mCrc);
|
||
}
|
||
|
||
res_t & value() {
|
||
return mCrc;
|
||
}
|
||
|
||
~CrcVal () {
|
||
--mCrcTbl;
|
||
}
|
||
};
|
||
/**
|
||
* @brief Подсчет контрольной суммы блока данных
|
||
* @param Param тип описывающий алгоритм подсчета (см. CrcDesc.hpp)
|
||
* @param pData указатель на блок данных
|
||
* @param nBytes размер блока данных в байтах (октеты)
|
||
* @param crcOld объект хранения текущего значения контрольной суммы
|
||
* @retval Обновленный объект хранения значения контрольной суммы
|
||
* @detailed Возможны два типа запуска: с параметром по умолчанию - создаем
|
||
* новое инициализированное хранилище на выходе (начало расчета),
|
||
* используем существующее хранилище - добавление результата расчета
|
||
* очередного блока данных.
|
||
*/
|
||
template <typename Param>
|
||
typename Param::crc_t crcCalc( const char * pData, uint32_t nBytes,
|
||
const typename Param::crc_t & crcOld = typename Param::crc_t() ) {
|
||
|
||
typename Param::res_t & crc = crcOld.value();
|
||
uint16_t data, octet = 0; (void)octet;
|
||
|
||
while ( nBytes-- ) {
|
||
#ifdef __TMS320C2000__
|
||
data = __byte( (int*)pData, octet );// nSize -= octet;
|
||
octet ^= 1; pData += !octet;// Адрес следующего слова данных
|
||
#endif
|
||
#ifdef __GNUG__
|
||
data = *pData++;
|
||
#endif
|
||
data &= 0xFF;
|
||
crc = Param::reflect ?
|
||
crcOld.mCrcTbl[data^(crc & 0xFF)] ^ (crc >> 8):
|
||
crcOld.mCrcTbl[data^(crc >> (Param::width_bit-8) & 0xFF)] ^ (crc << 8);
|
||
}
|
||
|
||
return crcOld;
|
||
}
|
||
} // namespace crc
|
||
} // namespace common
|
||
|
||
#include "CrcDesc.hpp"
|
||
|
||
#endif /* SOURCE_COMMON_CRC_HPP_ */
|