/** * @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 #include namespace common { namespace crc { /** * @brief Менеджер таблицы расчета контрольной суммы * @param Param тип описывающий алгоритм подсчета (см. CrcDesc.hpp) * @detailed Ведет подсчет ссылок на объекты хранения контрольной суммы для * обеспечивая выденленным на куче таблицей расчета CRC. Удаляем таблицу * при уничтожении всех объекты хранения контрольной суммы. */ template 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 CrcTable& CrcTable::Instance() { static CrcTable mObj; return mObj; } /** * @brief Хранилище значения контрольной суммы * @detailed Взаимодействует c CrcTable обеспечивая доступ к таблице * для расчета CRC. Обеспечивает начальный и конечный этап получения * контрольной суммы. Реализует операторы приведения типа возвращающий * конечную стадию (XOR) вычисления CRC. */ template class CrcVal { typedef typename Param::res_t res_t; res_t mCrc; public: CrcTable & mCrcTbl; public: CrcVal () : mCrc(Param::init), mCrcTbl(CrcTable::Instance()) { ++mCrcTbl; } CrcVal & operator=(const CrcVal & obj) { mCrc = obj.mCrc; return *this; } CrcVal( const CrcVal & obj ) : mCrcTbl(CrcTable::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(mCrc); } res_t & value() { return mCrc; } ~CrcVal () { --mCrcTbl; } }; /** * @brief Подсчет контрольной суммы блока данных * @param Param тип описывающий алгоритм подсчета (см. CrcDesc.hpp) * @param pData указатель на блок данных * @param nBytes размер блока данных в байтах (октеты) * @param crcOld объект хранения текущего значения контрольной суммы * @retval Обновленный объект хранения значения контрольной суммы * @detailed Возможны два типа запуска: с параметром по умолчанию - создаем * новое инициализированное хранилище на выходе (начало расчета), * используем существующее хранилище - добавление результата расчета * очередного блока данных. */ template 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_ */