From 1ee69b9b51220c6127439c6f1ea1d49eda73e0b2 Mon Sep 17 00:00:00 2001 From: "Alan M. Carroll" Date: Sat, 8 Sep 2018 20:48:12 -0500 Subject: [PATCH] Hash: Add hash_immediate to generic hash and FNV hashes. --- include/tscore/Hash.h | 49 ++++++++++-- include/tscore/HashFNV.h | 168 ++++++++++++++++++++++++++++----------- include/tscore/HashMD5.h | 14 ++-- include/tscore/HashSip.h | 6 +- src/tscore/HashFNV.cc | 58 -------------- src/tscore/HashMD5.cc | 24 +++--- src/tscore/HashSip.cc | 9 ++- src/tscore/Makefile.am | 1 - 8 files changed, 191 insertions(+), 138 deletions(-) delete mode 100644 src/tscore/HashFNV.cc diff --git a/include/tscore/Hash.h b/include/tscore/Hash.h index 68879a93951..b7045d828c5 100644 --- a/include/tscore/Hash.h +++ b/include/tscore/Hash.h @@ -26,9 +26,9 @@ #include struct ATSHashBase { - virtual void update(const void *, size_t) = 0; - virtual void final(void) = 0; - virtual void clear(void) = 0; + virtual ATSHashBase &update(const void *, size_t) = 0; + virtual ATSHashBase & final(void) = 0; + virtual ATSHashBase &clear(void) = 0; virtual ~ATSHashBase(); }; @@ -55,11 +55,50 @@ struct ATSHash : ATSHashBase { }; struct ATSHash32 : ATSHashBase { - virtual uint32_t get(void) const = 0; +protected: + using self_type = ATSHash32; + +public: + using value_type = uint32_t; + + // Co-vary the return type. + virtual self_type &update(const void *, size_t) override = 0; + virtual self_type & final(void) override = 0; + virtual self_type &clear(void) override = 0; + + virtual value_type get(void) const = 0; virtual bool operator==(const ATSHash32 &) const; + value_type hash_immediate(void *data, size_t len); }; struct ATSHash64 : ATSHashBase { - virtual uint64_t get(void) const = 0; +protected: + using self_type = ATSHash64; + +public: + using value_type = uint64_t; + + // Co-vary the return type. + virtual self_type &update(const void *, size_t) override = 0; + virtual self_type & final(void) override = 0; + virtual self_type &clear(void) override = 0; + + virtual value_type get(void) const = 0; virtual bool operator==(const ATSHash64 &) const; + value_type hash_immediate(void *data, size_t len); }; + +// ---- +// Implementation + +inline ATSHash32::value_type +ATSHash32::hash_immediate(void *data, size_t len) +{ + return this->update(data, len).final().get(); +} + +inline ATSHash64::value_type +ATSHash64::hash_immediate(void *data, size_t len) +{ + return this->update(data, len).final().get(); +} diff --git a/include/tscore/HashFNV.h b/include/tscore/HashFNV.h index e113d0cd012..1c0571d2271 100644 --- a/include/tscore/HashFNV.h +++ b/include/tscore/HashFNV.h @@ -2,21 +2,18 @@ @section license License - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you 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 + Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. + See the NOTICE file distributed with this work for additional information regarding copyright + ownership. The ASF licenses this file to you 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. + 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. */ /* @@ -27,67 +24,142 @@ #pragma once -#include "tscore/Hash.h" #include +#include "tscore/Hash.h" struct ATSHash32FNV1a : ATSHash32 { - ATSHash32FNV1a(void); +protected: + using self_type = ATSHash32FNV1a; + using super_type = ATSHash32; + static constexpr uint32_t INIT = 0x811c9dc5u; - template void update(const void *data, size_t len, Transform xfrm); - void - update(const void *data, size_t len) override - { - update(data, len, ATSHash::nullxfrm()); - } +public: + ATSHash32FNV1a() = default; + + template self_type &update(const void *data, size_t len, const Transform &xf); + + self_type &update(const void *data, size_t len) override; + + self_type & final() override; + value_type get() const override; + self_type &clear() override; - void final(void) override; - uint32_t get(void) const override; - void clear(void) override; + template uint32_t hash_immediate(const void *data, size_t len, const Transform &xf); private: - uint32_t hval; + value_type hval{INIT}; }; +struct ATSHash64FNV1a : ATSHash64 { +protected: + using self_type = ATSHash64FNV1a; + using super_type = ATSHash64; + static constexpr uint64_t INIT = 0xcbf29ce484222325ull; + +public: + ATSHash64FNV1a() = default; + + template self_type &update(const void *data, size_t len, const Transform &xf); + self_type &update(const void *data, size_t len) override; + + self_type & final() override; + value_type get() const override; + self_type &clear() override; + + template value_type hash_immediate(const void *data, size_t len, const Transform &xf); + +private: + value_type hval{INIT}; +}; + +// ---------- +// Implementation + +// -- 32 -- + +inline auto +ATSHash32FNV1a::clear() -> self_type & +{ + hval = INIT; + return *this; +} + template -void -ATSHash32FNV1a::update(const void *data, size_t len, Transform xfrm) +auto +ATSHash32FNV1a::update(const void *data, size_t len, const Transform &xf) -> self_type & { - uint8_t *bp = (uint8_t *)data; - uint8_t *be = bp + len; + const uint8_t *bp = static_cast(data); + const uint8_t *be = bp + len; for (; bp < be; ++bp) { - hval ^= (uint32_t)xfrm(*bp); + hval ^= static_cast(xf(*bp)); hval += (hval << 1) + (hval << 4) + (hval << 7) + (hval << 8) + (hval << 24); } + return *this; } -struct ATSHash64FNV1a : ATSHash64 { - ATSHash64FNV1a(void); +inline auto +ATSHash32FNV1a::update(const void *data, size_t len) -> self_type & +{ + return this->update(data, len, ATSHash::nullxfrm()); +} - template void update(const void *data, size_t len, Transform xfrm); - void - update(const void *data, size_t len) override - { - update(data, len, ATSHash::nullxfrm()); - } +inline auto +ATSHash32FNV1a::final() -> self_type & +{ + return *this; +} - void final(void) override; - uint64_t get(void) const override; - void clear(void) override; +inline auto +ATSHash32FNV1a::get() const -> value_type +{ + return hval; +} -private: - uint64_t hval; -}; +// -- 64 -- + +inline auto +ATSHash64FNV1a::clear() -> self_type & +{ + hval = INIT; + return *this; +} template -void -ATSHash64FNV1a::update(const void *data, size_t len, Transform xfrm) +auto +ATSHash64FNV1a::update(const void *data, size_t len, const Transform &xf) -> self_type & { - uint8_t *bp = (uint8_t *)data; - uint8_t *be = bp + len; + const uint8_t *bp = static_cast(data); + const uint8_t *be = bp + len; for (; bp < be; ++bp) { - hval ^= (uint64_t)xfrm(*bp); + hval ^= static_cast(xf(*bp)); hval += (hval << 1) + (hval << 4) + (hval << 5) + (hval << 7) + (hval << 8) + (hval << 40); } + return *this; +} + +inline auto +ATSHash64FNV1a::update(const void *data, size_t len) -> self_type & +{ + return this->update(data, len, ATSHash::nullxfrm()); +} + +template +auto +ATSHash32FNV1a::hash_immediate(const void *data, size_t len, const Transform &xf) -> value_type +{ + return this->update(data, len, xf).final().get(); +} + +inline auto +ATSHash64FNV1a::final() -> self_type & +{ + return *this; +} + +inline auto +ATSHash64FNV1a::get() const -> value_type +{ + return hval; } diff --git a/include/tscore/HashMD5.h b/include/tscore/HashMD5.h index bad5a90cc80..42afb2ac3c3 100644 --- a/include/tscore/HashMD5.h +++ b/include/tscore/HashMD5.h @@ -25,17 +25,17 @@ #include struct ATSHashMD5 : ATSHash { - ATSHashMD5(void); - void update(const void *data, size_t len) override; - void final(void) override; + ATSHashMD5(); + ATSHashMD5 &update(const void *data, size_t len) override; + ATSHashMD5 & final(void) override; const void *get(void) const override; size_t size(void) const override; - void clear(void) override; + ATSHashMD5 &clear(void) override; ~ATSHashMD5() override; private: - EVP_MD_CTX *ctx; + EVP_MD_CTX *ctx{nullptr}; unsigned char md_value[EVP_MAX_MD_SIZE]; - unsigned int md_len; - bool finalized; + unsigned int md_len{0}; + bool finalized{false}; }; diff --git a/include/tscore/HashSip.h b/include/tscore/HashSip.h index 837289848dc..f8797404883 100644 --- a/include/tscore/HashSip.h +++ b/include/tscore/HashSip.h @@ -35,10 +35,10 @@ struct ATSHash64Sip24 : ATSHash64 { ATSHash64Sip24(void); ATSHash64Sip24(const unsigned char key[16]); ATSHash64Sip24(std::uint64_t key0, std::uint64_t key1); - void update(const void *data, std::size_t len) override; - void final(void) override; + ATSHash64Sip24 &update(const void *data, std::size_t len) override; + ATSHash64Sip24 & final(void) override; std::uint64_t get(void) const override; - void clear(void) override; + ATSHash64Sip24 &clear(void) override; private: unsigned char block_buffer[8] = {0}; diff --git a/src/tscore/HashFNV.cc b/src/tscore/HashFNV.cc deleted file mode 100644 index b060ab4205a..00000000000 --- a/src/tscore/HashFNV.cc +++ /dev/null @@ -1,58 +0,0 @@ -/* - This algorithm is in the public domain. This code was - derived from code in the public domain. - - http://www.isthe.com/chongo/tech/comp/fnv/ - - Currently implemented FNV-1a 32bit and FNV-1a 64bit - */ - -#include "tscore/HashFNV.h" - -static const uint32_t FNV_INIT_32 = 0x811c9dc5u; -static const uint64_t FNV_INIT_64 = 0xcbf29ce484222325ull; - -// FNV-1a 64bit -ATSHash32FNV1a::ATSHash32FNV1a() -{ - this->clear(); -} - -void -ATSHash32FNV1a::final() -{ -} - -uint32_t -ATSHash32FNV1a::get() const -{ - return hval; -} - -void -ATSHash32FNV1a::clear() -{ - hval = FNV_INIT_32; -} - -// FNV-1a 64bit -ATSHash64FNV1a::ATSHash64FNV1a() -{ - this->clear(); -} -void -ATSHash64FNV1a::final() -{ -} - -uint64_t -ATSHash64FNV1a::get() const -{ - return hval; -} - -void -ATSHash64FNV1a::clear() -{ - hval = FNV_INIT_64; -} diff --git a/src/tscore/HashMD5.cc b/src/tscore/HashMD5.cc index 7f1dedc1b80..74170dc7e99 100644 --- a/src/tscore/HashMD5.cc +++ b/src/tscore/HashMD5.cc @@ -23,23 +23,23 @@ #include "tscore/ink_config.h" #include "tscore/HashMD5.h" -ATSHashMD5::ATSHashMD5() : md_len(0), finalized(false) +ATSHashMD5::ATSHashMD5() : ctx(EVP_MD_CTX_new()) { - ctx = EVP_MD_CTX_new(); int ret = EVP_DigestInit_ex(ctx, EVP_md5(), nullptr); ink_assert(ret == 1); } -void +ATSHashMD5 & ATSHashMD5::update(const void *data, size_t len) { if (!finalized) { int ret = EVP_DigestUpdate(ctx, data, len); ink_assert(ret == 1); } + return *this; } -void +ATSHashMD5 & ATSHashMD5::final() { if (!finalized) { @@ -47,16 +47,13 @@ ATSHashMD5::final() ink_assert(ret == 1); finalized = true; } + return *this; } const void * ATSHashMD5::get() const { - if (finalized) { - return (void *)md_value; - } else { - return nullptr; - } + return finalized ? md_value : nullptr; } size_t @@ -65,21 +62,22 @@ ATSHashMD5::size() const return EVP_MD_CTX_size(ctx); } -void +ATSHashMD5 & ATSHashMD5::clear() { + int ret = 1; #ifndef OPENSSL_IS_BORINGSSL - int ret = EVP_MD_CTX_reset(ctx); + ret = EVP_MD_CTX_reset(ctx); + ink_assert(ret == 1); #else // OpenSSL's EVP_MD_CTX_reset always returns 1 - int ret = 1; EVP_MD_CTX_reset(ctx); #endif - ink_assert(ret == 1); ret = EVP_DigestInit_ex(ctx, EVP_md5(), nullptr); ink_assert(ret == 1); md_len = 0; finalized = false; + return *this; } ATSHashMD5::~ATSHashMD5() diff --git a/src/tscore/HashSip.cc b/src/tscore/HashSip.cc index bc0db100556..960e17d7374 100644 --- a/src/tscore/HashSip.cc +++ b/src/tscore/HashSip.cc @@ -50,7 +50,7 @@ ATSHash64Sip24::ATSHash64Sip24(uint64_t key0, uint64_t key1) : k0(key0), k1(key1 this->clear(); } -void +ATSHash64Sip24 & ATSHash64Sip24::update(const void *data, size_t len) { size_t i, blocks; @@ -89,9 +89,10 @@ ATSHash64Sip24::update(const void *data, size_t len) memcpy(block_buffer, m + block_off + blocks, block_buffer_len); } } + return *this; } -void +ATSHash64Sip24 & ATSHash64Sip24::final() { uint64_t last7; @@ -116,6 +117,7 @@ ATSHash64Sip24::final() hfinal = v0 ^ v1 ^ v2 ^ v3; finalized = true; } + return *this; } uint64_t @@ -128,7 +130,7 @@ ATSHash64Sip24::get() const } } -void +ATSHash64Sip24 & ATSHash64Sip24::clear() { v0 = k0 ^ 0x736f6d6570736575ull; @@ -138,4 +140,5 @@ ATSHash64Sip24::clear() finalized = false; total_len = 0; block_buffer_len = 0; + return *this; } diff --git a/src/tscore/Makefile.am b/src/tscore/Makefile.am index 2221bb76b4b..be9f80633d6 100644 --- a/src/tscore/Makefile.am +++ b/src/tscore/Makefile.am @@ -77,7 +77,6 @@ libtscore_la_SOURCES = \ fastlz.c \ fastlz.h \ Hash.cc \ - HashFNV.cc \ HashFNV.h \ Hash.h \ HashMD5.cc \