diff options
author | Devtools Arcadia <arcadia-devtools@yandex-team.ru> | 2022-02-07 18:08:42 +0300 |
---|---|---|
committer | Devtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net> | 2022-02-07 18:08:42 +0300 |
commit | 1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch) | |
tree | e26c9fed0de5d9873cce7e00bc214573dc2195b7 /library/cpp/digest/lower_case | |
download | ydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz |
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'library/cpp/digest/lower_case')
-rw-r--r-- | library/cpp/digest/lower_case/hash_ops.cpp | 23 | ||||
-rw-r--r-- | library/cpp/digest/lower_case/hash_ops.h | 13 | ||||
-rw-r--r-- | library/cpp/digest/lower_case/hash_ops_ut.cpp | 36 | ||||
-rw-r--r-- | library/cpp/digest/lower_case/lchash.cpp | 1 | ||||
-rw-r--r-- | library/cpp/digest/lower_case/lchash.h | 18 | ||||
-rw-r--r-- | library/cpp/digest/lower_case/lchash_ut.cpp | 21 | ||||
-rw-r--r-- | library/cpp/digest/lower_case/lciter.cpp | 1 | ||||
-rw-r--r-- | library/cpp/digest/lower_case/lciter.h | 42 | ||||
-rw-r--r-- | library/cpp/digest/lower_case/ut/ya.make | 13 | ||||
-rw-r--r-- | library/cpp/digest/lower_case/ya.make | 14 |
10 files changed, 182 insertions, 0 deletions
diff --git a/library/cpp/digest/lower_case/hash_ops.cpp b/library/cpp/digest/lower_case/hash_ops.cpp new file mode 100644 index 0000000000..3f1746d830 --- /dev/null +++ b/library/cpp/digest/lower_case/hash_ops.cpp @@ -0,0 +1,23 @@ +#include "lchash.h" +#include "lciter.h" +#include "hash_ops.h" + +#include <util/generic/algorithm.h> + +size_t TCIOps::operator()(const TStringBuf& s) const noexcept { + return FnvCaseLess(s, (size_t)0xBEE); +} + +size_t TCIOps::operator()(const char* s) const noexcept { + return operator()(TStringBuf(s)); +} + +bool TCIOps::operator()(const TStringBuf& f, const TStringBuf& s) const noexcept { + using TIter = TLowerCaseIterator<const char>; + + return (f.size() == s.size()) && Equal(TIter(f.begin()), TIter(f.end()), TIter(s.begin())); +} + +bool TCIOps::operator()(const char* f, const char* s) const noexcept { + return operator()(TStringBuf(f), TStringBuf(s)); +} diff --git a/library/cpp/digest/lower_case/hash_ops.h b/library/cpp/digest/lower_case/hash_ops.h new file mode 100644 index 0000000000..83ebf7aca4 --- /dev/null +++ b/library/cpp/digest/lower_case/hash_ops.h @@ -0,0 +1,13 @@ +#pragma once + +#include <util/generic/strbuf.h> + +// can be used for caseless hashes like: THashMap<TStringBuf, T, TCIOps, TCIOps> + +struct TCIOps { + size_t operator()(const char* s) const noexcept; + size_t operator()(const TStringBuf& s) const noexcept; + + bool operator()(const char* f, const char* s) const noexcept; + bool operator()(const TStringBuf& f, const TStringBuf& s) const noexcept; +}; diff --git a/library/cpp/digest/lower_case/hash_ops_ut.cpp b/library/cpp/digest/lower_case/hash_ops_ut.cpp new file mode 100644 index 0000000000..a7ab0b86ea --- /dev/null +++ b/library/cpp/digest/lower_case/hash_ops_ut.cpp @@ -0,0 +1,36 @@ +#include "hash_ops.h" + +#include <library/cpp/testing/unittest/registar.h> + +Y_UNIT_TEST_SUITE(TestCIHash) { + Y_UNIT_TEST(TestYHash1) { + THashMap<TStringBuf, int, TCIOps, TCIOps> h; + + h["Ab"] = 1; + h["aB"] = 2; + + UNIT_ASSERT_VALUES_EQUAL(h.size(), 1); + UNIT_ASSERT_VALUES_EQUAL(h["ab"], 2); + } + + Y_UNIT_TEST(TestYHash2) { + THashMap<const char*, int, TCIOps, TCIOps> h; + + h["Ab"] = 1; + h["aB"] = 2; + + UNIT_ASSERT_VALUES_EQUAL(h.size(), 1); + UNIT_ASSERT_VALUES_EQUAL(h["ab"], 2); + + h["Bc"] = 2; + h["bC"] = 3; + + UNIT_ASSERT_VALUES_EQUAL(h.size(), 2); + UNIT_ASSERT_VALUES_EQUAL(h["bc"], 3); + } + + Y_UNIT_TEST(Test1) { + UNIT_ASSERT_VALUES_EQUAL(TCIOps()("aBc3"), TCIOps()(TStringBuf("AbC3"))); + UNIT_ASSERT(TCIOps()("aBc4", "AbC4")); + } +} diff --git a/library/cpp/digest/lower_case/lchash.cpp b/library/cpp/digest/lower_case/lchash.cpp new file mode 100644 index 0000000000..92b4245533 --- /dev/null +++ b/library/cpp/digest/lower_case/lchash.cpp @@ -0,0 +1 @@ +#include "lchash.h" diff --git a/library/cpp/digest/lower_case/lchash.h b/library/cpp/digest/lower_case/lchash.h new file mode 100644 index 0000000000..6a287d9479 --- /dev/null +++ b/library/cpp/digest/lower_case/lchash.h @@ -0,0 +1,18 @@ +#pragma once + +#include "lciter.h" + +#include <util/digest/fnv.h> +#include <util/generic/strbuf.h> + +template <class T> +static inline T FnvCaseLess(const char* b, size_t l, T t = 0) noexcept { + using TIter = TLowerCaseIterator<const char>; + + return FnvHash(TIter(b), TIter(b + l), t); +} + +template <class T> +static inline T FnvCaseLess(const TStringBuf& s, T t = 0) noexcept { + return FnvCaseLess(s.data(), s.size(), t); +} diff --git a/library/cpp/digest/lower_case/lchash_ut.cpp b/library/cpp/digest/lower_case/lchash_ut.cpp new file mode 100644 index 0000000000..5711fe7cd7 --- /dev/null +++ b/library/cpp/digest/lower_case/lchash_ut.cpp @@ -0,0 +1,21 @@ +#include "lchash.h" + +#include <library/cpp/testing/unittest/registar.h> + +Y_UNIT_TEST_SUITE(TWebDaemonHash) { + Y_UNIT_TEST(Stability) { + UNIT_ASSERT_VALUES_EQUAL(FnvCaseLess<ui64>("blah"), ULL(5923727754379976229)); + UNIT_ASSERT_VALUES_EQUAL(FnvCaseLess<ui64>("blahminor"), ULL(8755704309003440816)); + } + + Y_UNIT_TEST(CaseLess) { + UNIT_ASSERT_VALUES_EQUAL(FnvCaseLess<ui64>("blah"), FnvCaseLess<ui64>("bLah")); + UNIT_ASSERT_VALUES_EQUAL(FnvCaseLess<ui64>("blah"), FnvCaseLess<ui64>("blAh")); + UNIT_ASSERT_VALUES_EQUAL(FnvCaseLess<ui64>("blah"), FnvCaseLess<ui64>("BLAH")); + } + + Y_UNIT_TEST(Robustness) { + UNIT_ASSERT(FnvCaseLess<ui64>("x-real-ip") != FnvCaseLess<ui64>("x-req-id")); + UNIT_ASSERT(FnvCaseLess<ui64>("x-real-ip") != FnvCaseLess<ui64>("x-start-time")); + } +} diff --git a/library/cpp/digest/lower_case/lciter.cpp b/library/cpp/digest/lower_case/lciter.cpp new file mode 100644 index 0000000000..38d23eb2dd --- /dev/null +++ b/library/cpp/digest/lower_case/lciter.cpp @@ -0,0 +1 @@ +#include "lciter.h" diff --git a/library/cpp/digest/lower_case/lciter.h b/library/cpp/digest/lower_case/lciter.h new file mode 100644 index 0000000000..9538e57932 --- /dev/null +++ b/library/cpp/digest/lower_case/lciter.h @@ -0,0 +1,42 @@ +#pragma once + +#include <util/generic/typetraits.h> +#include <util/string/ascii.h> + +#include <iterator> + +template <class T> +struct TLowerCaseIterator: public std::iterator<std::input_iterator_tag, T> { + using TNonConst = std::remove_const_t<T>; + + inline TLowerCaseIterator(T* c) + : C(c) + { + } + + inline TLowerCaseIterator& operator++() noexcept { + ++C; + + return *this; + } + + inline TLowerCaseIterator operator++(int) noexcept { + return C++; + } + + inline TNonConst operator*() const noexcept { + return AsciiToLower(*C); + } + + T* C; +}; + +template <class T> +inline bool operator==(const TLowerCaseIterator<T>& l, const TLowerCaseIterator<T>& r) noexcept { + return l.C == r.C; +} + +template <class T> +inline bool operator!=(const TLowerCaseIterator<T>& l, const TLowerCaseIterator<T>& r) noexcept { + return !(l == r); +} diff --git a/library/cpp/digest/lower_case/ut/ya.make b/library/cpp/digest/lower_case/ut/ya.make new file mode 100644 index 0000000000..f083257b3d --- /dev/null +++ b/library/cpp/digest/lower_case/ut/ya.make @@ -0,0 +1,13 @@ +UNITTEST_FOR(library/cpp/digest/lower_case) + +OWNER( + pg + g:util +) + +SRCS( + lchash_ut.cpp + hash_ops_ut.cpp +) + +END() diff --git a/library/cpp/digest/lower_case/ya.make b/library/cpp/digest/lower_case/ya.make new file mode 100644 index 0000000000..62cc16556a --- /dev/null +++ b/library/cpp/digest/lower_case/ya.make @@ -0,0 +1,14 @@ +LIBRARY() + +OWNER( + pg + g:util +) + +SRCS( + lciter.cpp + lchash.cpp + hash_ops.cpp +) + +END() |