/* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * Copyright 2011 Danny Robson */ #include "crc.hpp" #include "../bitwise.hpp" #include using cruft::hash::crc; /////////////////////////////////////////////////////////////////////////////// template < typename DigestT, DigestT Generator, DigestT Initial, DigestT Final, bool ReflectIn, bool ReflectOut > const std::array crc< DigestT,Generator,Initial,Final,ReflectIn,ReflectOut >::s_table = crc::table (); /////////////////////////////////////////////////////////////////////////////// template < typename DigestT, DigestT Generator, DigestT Initial, DigestT Final, bool ReflectIn, bool ReflectOut > typename crc::digest_t crc< DigestT,Generator,Initial,Final,ReflectIn,ReflectOut >::operator() (const cruft::view data) const noexcept { auto accum = Initial; for (auto i: data) { if (ReflectIn) accum = s_table[i ^ (accum & 0xFFu)] ^ (accum >> 8u); else { constexpr auto shift = sizeof (DigestT) * 8u - 8u; accum = (accum << 8u) ^ s_table[(accum >> shift) ^ i]; } } return (ReflectIn != ReflectOut ? cruft::reverse (accum) : accum) ^ Final; } /////////////////////////////////////////////////////////////////////////////// template < typename DigestT, DigestT Generator, DigestT Initial, DigestT Final, bool ReflectIn, bool ReflectOut > constexpr std::array cruft::hash::crc< DigestT,Generator,Initial,Final,ReflectIn,ReflectOut >::table (void) { // We want to use a std::array here for a (slight) safety advantage, but // it means that we have to use calls to array::data instead of operator[] // to retain constexpr. std::array values {}; if (ReflectIn) { constexpr auto gen = cruft::reverse (Generator); for (int i = 0; i < 256; ++i) { digest_t c = i; for (int k = 0; k < 8; ++k) { if (c & 1) c = gen ^ (c >> 1); else c >>= 1; } values.data ()[i] = c; } } else { constexpr DigestT shift = sizeof (DigestT) * 8u - 8u; constexpr DigestT highbit = DigestT(1) << (sizeof (DigestT) * 8u - 1u); for (int idx = 0; idx < 256; ++idx) { DigestT c = DigestT (idx) << shift; for (int i = 0; i < 8; ++i) { if (c & highbit) c = (c << DigestT (1)) ^ Generator; else c <<= DigestT(1); } values.data()[idx] = c; } } return values; }; /////////////////////////////////////////////////////////////////////////////// template class cruft::hash::crc; // crc32 template class cruft::hash::crc; // crc32b template class cruft::hash::crc; // crc32c template class cruft::hash::crc; // crc32d template class cruft::hash::crc; // ogg template class cruft::hash::crc; // crc64