From 51e7995c63be5b096e3d7685f5f938907fa06384 Mon Sep 17 00:00:00 2001 From: Danny Robson Date: Mon, 20 Jun 2016 16:37:43 +1000 Subject: [PATCH] hash/adler: convert to object style accumulator --- Makefile.am | 1 + hash/adler.cpp | 38 ++++++++++++-------- hash/adler.hpp | 12 ++++--- hash/fletcher.cpp | 89 +++++++++++++++++++++++++++++++++++++++++++++++ hash/fletcher.hpp | 51 +++++++++++++++------------ 5 files changed, 150 insertions(+), 41 deletions(-) create mode 100644 hash/fletcher.cpp diff --git a/Makefile.am b/Makefile.am index b959a877..f9e61f47 100644 --- a/Makefile.am +++ b/Makefile.am @@ -115,6 +115,7 @@ UTIL_FILES = \ hash/crc.hpp \ hash/fasthash.cpp \ hash/fasthash.hpp \ + hash/fletcher.cpp \ hash/fletcher.hpp \ hash/fnv1a.cpp \ hash/fnv1a.hpp \ diff --git a/hash/adler.cpp b/hash/adler.cpp index cc2d1d7b..8a1102ec 100644 --- a/hash/adler.cpp +++ b/hash/adler.cpp @@ -19,23 +19,31 @@ #include "./fletcher.hpp" #include "../debug.hpp" -static const unsigned MODULUS = 65521; +static constexpr unsigned MODULUS = 65521; + +using util::hash::adler32; /////////////////////////////////////////////////////////////////////////////// -uint32_t -util::hash::adler32 (const void* restrict _data, size_t _size) noexcept -{ - return adler32 ( - static_cast (_data), - static_cast (_data) + _size - ); -} +adler32::adler32 (): + fletcher (MODULUS, 1, 0) +{ ; } -//----------------------------------------------------------------------------- -uint32_t -util::hash::adler32 (const uint8_t *restrict first, const uint8_t *restrict last) noexcept -{ - return fletcher<32, MODULUS, 1, 0> (first, last - first); -} +///////////////////////////////////////////////////////////////////////////////// +//uint32_t +//util::hash::adler32 (const void* restrict _data, size_t _size) noexcept +//{ +// return adler32 ( +// static_cast (_data), +// static_cast (_data) + _size +// ); +//} +// +// +////----------------------------------------------------------------------------- +//uint32_t +//util::hash::adler32 (const uint8_t *restrict first, const uint8_t *restrict last) noexcept +//{ +// return fletcher<32, MODULUS, 1, 0> (first, last - first); +//} diff --git a/hash/adler.hpp b/hash/adler.hpp index 76946661..37b99f66 100644 --- a/hash/adler.hpp +++ b/hash/adler.hpp @@ -14,8 +14,10 @@ * Copyright 2010-2014 Danny Robson */ -#ifndef __UTIL_ADLER_HPP -#define __UTIL_ADLER_HPP +#ifndef __UTIL_HASH_ADLER_HPP +#define __UTIL_HASH_ADLER_HPP + +#include "./fletcher.hpp" #include #include @@ -23,8 +25,10 @@ /////////////////////////////////////////////////////////////////////////////// namespace util { namespace hash { - uint32_t adler32 (const void* restrict, size_t) noexcept; - uint32_t adler32 (const uint8_t *restrict first, const uint8_t *restrict last) noexcept; + class adler32 : public fletcher { + public: + adler32 (); + }; } } #endif diff --git a/hash/fletcher.cpp b/hash/fletcher.cpp new file mode 100644 index 00000000..a29dac95 --- /dev/null +++ b/hash/fletcher.cpp @@ -0,0 +1,89 @@ +/* + * 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 2010 Danny Robson + */ + + +#include "./fletcher.hpp" + +#include "../debug.hpp" + + +using util::hash::fletcher; + + +/////////////////////////////////////////////////////////////////////////////// +template +fletcher::fletcher (part_t _modulus, part_t _a, part_t _b): + m_modulus { _modulus }, + m_initial { _a, _b }, + m_state { m_initial } +{ ; } + + +//----------------------------------------------------------------------------- +template +void +fletcher::reset (void) +{ + m_state = m_initial; +} + + +/////////////////////////////////////////////////////////////////////////////// +template +void +fletcher::update (const void *restrict data, size_t size) noexcept +{ + CHECK (data); + + auto first = static_cast (data); + update (first, first + size); +} + + +//----------------------------------------------------------------------------- +template +void +fletcher::update (const uint8_t *restrict first, const uint8_t *restrict last) noexcept +{ + CHECK (first); + CHECK (last); + CHECK_LE (first, last); + + for (auto cursor = first; cursor < last; ++cursor) { + m_state.a = (m_state.a + *cursor ) % m_modulus; + m_state.b = (m_state.a + m_state.b) % m_modulus; + } +} + + +//----------------------------------------------------------------------------- +template +void +fletcher::finish (void) +{ ; } + + +/////////////////////////////////////////////////////////////////////////////// +template +typename fletcher::digest_t +fletcher::digest (void) const +{ + return (m_state.b << (sizeof (part_t) * 8)) + m_state.a; +} + + +/////////////////////////////////////////////////////////////////////////////// +template class util::hash::fletcher; diff --git a/hash/fletcher.hpp b/hash/fletcher.hpp index ca0210ce..7eebae5b 100644 --- a/hash/fletcher.hpp +++ b/hash/fletcher.hpp @@ -11,11 +11,11 @@ * See the License for the specific language governing permissions and * limitations under the License. * - * Copyright 2010 Danny Robson + * Copyright 2010-2016 Danny Robson */ -#ifndef __UTIL_FLETCHER_HPP -#define __UTIL_FLETCHER_HPP +#ifndef __UTIL_HASH_FLETCHER_HPP +#define __UTIL_HASH_FLETCHER_HPP #include "../types/bits.hpp" @@ -24,28 +24,35 @@ /////////////////////////////////////////////////////////////////////////////// -template < - unsigned OUTPUT, - unsigned MODULUS, - unsigned INITIAL_A, - unsigned INITIAL_B -> -typename bits_type::uint -fletcher (const void *restrict _data, - size_t size) -{ - typedef typename bits_type::uint temp_t; +namespace util { namespace hash { + template + class fletcher { + public: + using digest_t = DIGEST; + using part_t = typename bytes_type::uint; - auto data = static_cast (_data); - temp_t A = INITIAL_A, B = INITIAL_B; + fletcher (part_t modulus, part_t a, part_t b); - for (size_t i = 0; i < size; ++i) { - A = (A + data[i]) % MODULUS; - B = (A + B) % MODULUS; - } + void update (const void *restrict, size_t) noexcept; + void update (const uint8_t *restrict first, const uint8_t *restrict last) noexcept; + + void finish (void); + digest_t digest (void) const; + + void reset (void); + + private: + const digest_t m_modulus; + + struct state_t { + part_t a, b; + }; + + const state_t m_initial; + state_t m_state; + }; +} } - return (B << (OUTPUT / 2u)) + A; -} #endif