aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/digest/lower_case
diff options
context:
space:
mode:
authorDevtools Arcadia <arcadia-devtools@yandex-team.ru>2022-02-07 18:08:42 +0300
committerDevtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net>2022-02-07 18:08:42 +0300
commit1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch)
treee26c9fed0de5d9873cce7e00bc214573dc2195b7 /library/cpp/digest/lower_case
downloadydb-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.cpp23
-rw-r--r--library/cpp/digest/lower_case/hash_ops.h13
-rw-r--r--library/cpp/digest/lower_case/hash_ops_ut.cpp36
-rw-r--r--library/cpp/digest/lower_case/lchash.cpp1
-rw-r--r--library/cpp/digest/lower_case/lchash.h18
-rw-r--r--library/cpp/digest/lower_case/lchash_ut.cpp21
-rw-r--r--library/cpp/digest/lower_case/lciter.cpp1
-rw-r--r--library/cpp/digest/lower_case/lciter.h42
-rw-r--r--library/cpp/digest/lower_case/ut/ya.make13
-rw-r--r--library/cpp/digest/lower_case/ya.make14
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()