/* * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright 2011 Danny Robson */ #include "./crc.hpp" #include "../debug.hpp" #include #include using util::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 > crc< DigestT,Generator,Initial,Final,ReflectIn,ReflectOut >::crc () noexcept { reset (); } //----------------------------------------------------------------------------- template < typename DigestT, DigestT Generator, DigestT Initial, DigestT Final, bool ReflectIn, bool ReflectOut > void crc< DigestT,Generator,Initial,Final,ReflectIn,ReflectOut >::reset (void) noexcept { m_digest = Initial; } /////////////////////////////////////////////////////////////////////////////// template < typename DigestT, DigestT Generator, DigestT Initial, DigestT Final, bool ReflectIn, bool ReflectOut > void crc< DigestT,Generator,Initial,Final,ReflectIn,ReflectOut >::update (const uint8_t *restrict first, const uint8_t *restrict last) noexcept { CHECK_LE (first, last); for (auto cursor = first; cursor != last; ++cursor) { if (ReflectIn) m_digest = s_table[*cursor ^ (m_digest & 0xFFu)] ^ (m_digest >> 8u); else { constexpr auto shift = sizeof (DigestT) * 8u - 8u; m_digest = (m_digest << 8u) ^ s_table[(m_digest >> shift) ^ *cursor]; } } } //----------------------------------------------------------------------------- template < typename DigestT, DigestT Generator, DigestT Initial, DigestT Final, bool ReflectIn, bool ReflectOut > void crc< DigestT,Generator,Initial,Final,ReflectIn,ReflectOut >::update (const void *restrict _data, size_t len) noexcept { auto data = reinterpret_cast (_data); return update(data, data + len); } //----------------------------------------------------------------------------- template < typename DigestT, DigestT Generator, DigestT Initial, DigestT Final, bool ReflectIn, bool ReflectOut > void crc< DigestT,Generator,Initial,Final,ReflectIn,ReflectOut >::finish (void) { ; } //----------------------------------------------------------------------------- template < typename DigestT, DigestT Generator, DigestT Initial, DigestT Final, bool ReflectIn, bool ReflectOut > DigestT crc< DigestT,Generator,Initial,Final,ReflectIn,ReflectOut >::digest (void) const { return (ReflectIn != ReflectOut ? util::reverse (m_digest) : m_digest) ^ Final; } /////////////////////////////////////////////////////////////////////////////// template < typename DigestT, DigestT Generator, DigestT Initial, DigestT Final, bool ReflectIn, bool ReflectOut > constexpr std::array util::hash::crc< DigestT,Generator,Initial,Final,ReflectIn,ReflectOut >::table (void) { std::array values {}; if (ReflectIn) { constexpr auto gen = util::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 util::hash::crc; // crc32 template class util::hash::crc; // crc32b template class util::hash::crc; // crc32c template class util::hash::crc; // crc32d template class util::hash::crc; // ogg template class util::hash::crc; // crc64