aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp
diff options
context:
space:
mode:
authorarcadia-devtools <arcadia-devtools@yandex-team.ru>2022-02-08 18:25:47 +0300
committerarcadia-devtools <arcadia-devtools@yandex-team.ru>2022-02-08 18:25:47 +0300
commita3ac8a71f16e0db7d50d5b1235466ff754e0d228 (patch)
tree8433eb84ffae296ccb9ae094d08491c86c48bdb1 /library/cpp
parent60312eaed2e51caa7ed482270d3545a9d27cb284 (diff)
downloadydb-a3ac8a71f16e0db7d50d5b1235466ff754e0d228.tar.gz
intermediate changes
ref:f398132a6a7101a031da4a85ff8dc9f360af7d8a
Diffstat (limited to 'library/cpp')
-rw-r--r--library/cpp/digest/md5/bench/main.cpp13
-rw-r--r--library/cpp/digest/md5/bench/ya.make2
-rw-r--r--library/cpp/digest/md5/md5.cpp198
-rw-r--r--library/cpp/digest/md5/md5.h48
-rw-r--r--library/cpp/digest/md5/md5_ut.cpp8
-rw-r--r--library/cpp/testing/unittest/registar.h17
-rw-r--r--library/cpp/testing/unittest/registar_ut.cpp13
7 files changed, 159 insertions, 140 deletions
diff --git a/library/cpp/digest/md5/bench/main.cpp b/library/cpp/digest/md5/bench/main.cpp
index 8f6386d8a1..70672e6741 100644
--- a/library/cpp/digest/md5/bench/main.cpp
+++ b/library/cpp/digest/md5/bench/main.cpp
@@ -1,16 +1,15 @@
-#include <library/cpp/testing/benchmark/bench.h>
-#include <library/cpp/digest/md5/md5.h>
+#include <benchmark/benchmark.h>
-#include <util/generic/xrange.h>
+#include <library/cpp/digest/md5/md5.h>
#define MD5_DEF(N) \
- Y_CPU_BENCHMARK(MD5_##N, iface) { \
+ static void MD5Benchmark_##N(benchmark::State& st) { \
char buf[N]; \
- for (const auto i : xrange(iface.Iterations())) { \
- Y_UNUSED(i); \
+ for (auto _ : st) { \
Y_DO_NOT_OPTIMIZE_AWAY(MD5().Update(buf, sizeof(buf))); \
} \
- }
+ } \
+ BENCHMARK(MD5Benchmark_##N);
MD5_DEF(32)
MD5_DEF(64)
diff --git a/library/cpp/digest/md5/bench/ya.make b/library/cpp/digest/md5/bench/ya.make
index ad78159d8e..5c3e3c1c42 100644
--- a/library/cpp/digest/md5/bench/ya.make
+++ b/library/cpp/digest/md5/bench/ya.make
@@ -1,4 +1,4 @@
-Y_BENCHMARK()
+G_BENCHMARK()
OWNER(
pg
diff --git a/library/cpp/digest/md5/md5.cpp b/library/cpp/digest/md5/md5.cpp
index 27af7f88d7..24a5b69eef 100644
--- a/library/cpp/digest/md5/md5.cpp
+++ b/library/cpp/digest/md5/md5.cpp
@@ -1,19 +1,17 @@
#include "md5.h"
-#include <contrib/libs/nayuki_md5/md5.h>
+#include <library/cpp/string_utils/base64/base64.h>
-#include <util/generic/strbuf.h>
-#include <util/generic/string.h>
#include <util/stream/input.h>
#include <util/stream/file.h>
-#include <library/cpp/string_utils/base64/base64.h>
#include <util/string/hex.h>
-#include <cstring>
-#include <cstdlib>
+#include <contrib/libs/nayuki_md5/md5.h>
namespace {
+ constexpr size_t MD5_BLOCK_LENGTH = 64;
+ constexpr size_t MD5_PADDING_SHIFT = 56;
constexpr size_t MD5_HEX_DIGEST_LENGTH = 32;
struct TMd5Stream: public IOutputStream {
@@ -28,6 +26,14 @@ namespace {
MD5* M_;
};
+
+ inline TArrayRef<const ui8> MakeUnsignedArrayRef(const void* data, const size_t size) {
+ return MakeArrayRef(static_cast<const ui8*>(data), size);
+ }
+
+ inline TArrayRef<const ui8> MakeUnsignedArrayRef(const TArrayRef<const char>& data) {
+ return MakeUnsignedArrayRef(data.data(), data.size());
+ }
}
char* MD5::File(const char* filename, char* buf) {
@@ -51,30 +57,23 @@ TString MD5::File(const TString& filename) {
return buf;
}
-char* MD5::Data(const void* data, size_t len, char* buf) {
- MD5 md5;
- md5.Update(data, len);
- return md5.End(buf);
+char* MD5::Data(const TArrayRef<const ui8>& data, char* buf) {
+ return MD5().Update(data).End(buf);
}
-TString MD5::Data(TArrayRef<ui8> data) {
- MD5 md5;
- md5.Update(data.data(), data.size());
+char* MD5::Data(const void* data, size_t len, char* buf) {
+ return Data(MakeUnsignedArrayRef(data, len), buf);
+}
+TString MD5::Data(const TArrayRef<const ui8>& data) {
TString buf;
buf.ReserveAndResize(MD5_HEX_DIGEST_LENGTH);
- md5.End(buf.begin());
+ Data(data, buf.begin());
return buf;
}
TString MD5::Data(TStringBuf data) {
- MD5 md5;
- md5.Update(data.data(), data.size());
-
- TString buf;
- buf.ReserveAndResize(MD5_HEX_DIGEST_LENGTH);
- md5.End(buf.begin());
- return buf;
+ return Data(MakeUnsignedArrayRef(data));
}
char* MD5::Stream(IInputStream* in, char* buf) {
@@ -89,27 +88,7 @@ MD5& MD5::Update(IInputStream* in) {
return *this;
}
-static inline void MD5Transform(ui32 state[4], const unsigned char block[64]) {
- return md5_compress((uint32_t*)state, (const ui8*)block);
-}
-
-/*
- * Encodes input (ui32) into output (unsigned char). Assumes len is
- * a multiple of 4.
- */
-
-static void Encode(unsigned char* output, ui32* input, unsigned int len) {
- unsigned int i, j;
-
- for (i = 0, j = 0; j < len; i++, j += 4) {
- output[j] = (unsigned char)(input[i] & 0xff);
- output[j + 1] = (unsigned char)((input[i] >> 8) & 0xff);
- output[j + 2] = (unsigned char)((input[i] >> 16) & 0xff);
- output[j + 3] = (unsigned char)((input[i] >> 24) & 0xff);
- }
-}
-
-static unsigned char PADDING[64] = {
+static const ui8 PADDING[MD5_BLOCK_LENGTH] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
@@ -117,7 +96,8 @@ static unsigned char PADDING[64] = {
/* MD5 initialization. Begins an MD5 operation, writing a new context. */
void MD5::Init() {
- Count[0] = Count[1] = 0;
+ BufferSize = 0;
+ StreamSize = 0;
/* Load magic initialization constants. */
State[0] = 0x67452301;
State[1] = 0xefcdab89;
@@ -131,27 +111,30 @@ void MD5::Init() {
* context.
*/
-void MD5::UpdatePart(const void* inputPtr, unsigned int inputLen) {
- const unsigned char* input = (const unsigned char*)inputPtr;
- unsigned int i, index, partLen;
- /* Compute number of bytes mod 64 */
- index = (unsigned int)((Count[0] >> 3) & 0x3F);
- /* Update number of bits */
- if ((Count[0] += ((ui32)inputLen << 3)) < ((ui32)inputLen << 3))
- Count[1]++;
- Count[1] += ((ui32)inputLen >> 29);
- partLen = 64 - index;
- /* Transform as many times as possible. */
- if (inputLen >= partLen) {
- memcpy((void*)&Buffer[index], (const void*)input, partLen);
- MD5Transform(State, Buffer);
- for (i = partLen; i + 63 < inputLen; i += 64)
- MD5Transform(State, &input[i]);
- index = 0;
- } else
- i = 0;
- /* Buffer remaining input */
- memcpy((void*)&Buffer[index], (const void*)&input[i], inputLen - i);
+void MD5::UpdatePart(TArrayRef<const ui8> data) {
+ /* Count input bytes */
+ StreamSize += data.size();
+ if (BufferSize > 0) {
+ /* Filling remaining buffer */
+ const ui8 freeBufferSize = MD5_BLOCK_LENGTH - BufferSize;
+ const ui8 partLen = data.size() >= freeBufferSize ? freeBufferSize : data.size();
+ memcpy(&Buffer[BufferSize], data.data(), partLen);
+ BufferSize += partLen;
+ data = data.Slice(partLen);
+ if (BufferSize == MD5_BLOCK_LENGTH) {
+ /* Buffer is full and ready for hashing */
+ md5_compress(State, Buffer);
+ BufferSize = 0;
+ }
+ }
+ /* Processing input by chanks */
+ while (data.size() >= MD5_BLOCK_LENGTH) {
+ md5_compress(State, data.data());
+ data = data.Slice(MD5_BLOCK_LENGTH);
+ }
+ /* Save remaining input in buffer */
+ memcpy(Buffer, data.data(), data.size());
+ BufferSize += data.size();
}
/*
@@ -159,16 +142,19 @@ void MD5::UpdatePart(const void* inputPtr, unsigned int inputLen) {
*/
void MD5::Pad() {
- unsigned char bits[8];
- unsigned int index, padLen;
- /* Save number of bits */
- Encode(bits, Count, 8);
- /* Pad out to 56 mod 64. */
- index = (unsigned int)((Count[0] >> 3) & 0x3f);
- padLen = (index < 56) ? (56 - index) : (120 - index);
- Update(PADDING, padLen);
- /* Append length (before padding) */
- Update(bits, 8);
+ size_t streamSize = StreamSize;
+
+ const size_t paddingSize = (MD5_PADDING_SHIFT > BufferSize) ? (MD5_PADDING_SHIFT - BufferSize) : (MD5_PADDING_SHIFT + MD5_BLOCK_LENGTH - BufferSize);
+ Update(PADDING, paddingSize);
+
+ // Size of stream in bits
+ // If size greater than 2^64 - 1 only lower 64 bits used
+ streamSize <<= 3;
+ for (int i = 0; i < 8; ++i, streamSize >>= 8) {
+ // Storing in reverse order
+ Buffer[MD5_PADDING_SHIFT + i] = static_cast<ui8>(streamSize & 0xFFU);
+ }
+ md5_compress(State, Buffer);
}
/*
@@ -176,36 +162,35 @@ void MD5::Pad() {
* the message digest and zeroizing the context.
*/
-unsigned char* MD5::Final(unsigned char digest[16]) {
+ui8* MD5::Final(ui8 digest[16]) {
/* Do padding. */
Pad();
/* Store state in digest */
- Encode(digest, State, 16);
+ memcpy(digest, State, 16);
/* Zeroize sensitive information. */
- memset((void*)this, 0, sizeof(*this));
+ Init();
return digest;
}
char* MD5::End(char* buf) {
- unsigned char digest[16];
static const char hex[] = "0123456789abcdef";
+ ui8 digest[16];
if (!buf)
buf = (char*)malloc(33);
if (!buf)
return nullptr;
Final(digest);
- int i = 0;
- for (; i < 16; i++) {
- buf[i + i] = hex[digest[i] >> 4];
- buf[i + i + 1] = hex[digest[i] & 0x0f];
+ for (ui8 i = 0; i < MD5_HEX_DIGEST_LENGTH / 2; i++) {
+ buf[i * 2] = hex[digest[i] >> 4];
+ buf[i * 2 + 1] = hex[digest[i] & 0x0f];
}
- buf[i + i] = '\0';
+ buf[32] = '\0';
return buf;
}
char* MD5::End_b64(char* buf) {
- unsigned char digest[16];
+ ui8 digest[16];
if (!buf)
buf = (char*)malloc(25);
if (!buf)
@@ -217,7 +202,7 @@ char* MD5::End_b64(char* buf) {
}
ui64 MD5::EndHalfMix() {
- unsigned char digest[16];
+ ui8 digest[16];
Final(digest);
ui64 res = 0;
for (int i = 3; i >= 0; i--) {
@@ -227,40 +212,47 @@ ui64 MD5::EndHalfMix() {
return res;
}
-TString MD5::Calc(const TStringBuf& data) {
- TString result;
- result.resize(32);
+TString MD5::Calc(TStringBuf data) {
+ return Calc(MakeUnsignedArrayRef(data));
+}
- Data((const unsigned char*)data.data(), data.size(), result.begin());
+TString MD5::Calc(const TArrayRef<const ui8>& data) {
+ return Data(data);
+}
- return result;
+TString MD5::CalcRaw(TStringBuf data) {
+ return CalcRaw(MakeUnsignedArrayRef(data));
}
-TString MD5::CalcRaw(const TStringBuf& data) {
+TString MD5::CalcRaw(const TArrayRef<const ui8>& data) {
TString result;
- result.resize(16);
- MD5 md5;
- md5.Update(data.data(), data.size());
- md5.Final(reinterpret_cast<unsigned char*>(result.begin()));
+ result.ReserveAndResize(16);
+ MD5().Update(data).Final(reinterpret_cast<ui8*>(result.begin()));
return result;
}
ui64 MD5::CalcHalfMix(const char* data, size_t len) {
- MD5 md5;
- md5.Update(data, len);
- return md5.EndHalfMix();
+ return CalcHalfMix(MakeUnsignedArrayRef(data, len));
+}
+
+ui64 MD5::CalcHalfMix(TStringBuf data) {
+ return CalcHalfMix(MakeUnsignedArrayRef(data));
+}
+
+ui64 MD5::CalcHalfMix(const TArrayRef<const ui8>& data) {
+ return MD5().Update(data).EndHalfMix();
}
-ui64 MD5::CalcHalfMix(const TStringBuf& data) {
- return CalcHalfMix(data.data(), data.size());
+bool MD5::IsMD5(TStringBuf data) {
+ return IsMD5(MakeUnsignedArrayRef(data));
}
-bool MD5::IsMD5(const TStringBuf& data) {
+bool MD5::IsMD5(const TArrayRef<const ui8>& data) {
if (data.size() != 32) {
return false;
}
- for (const char *p = data.data(), *e = data.data() + data.size(); p != e; ++p) {
- if (Char2DigitTable[(unsigned char)*p] == '\xff') {
+ for (const ui8 *p = data.data(), *e = data.data() + data.size(); p != e; ++p) {
+ if (Char2DigitTable[*p] == '\xff') {
return false;
}
}
diff --git a/library/cpp/digest/md5/md5.h b/library/cpp/digest/md5/md5.h
index 1568567e3c..2c17aa0518 100644
--- a/library/cpp/digest/md5/md5.h
+++ b/library/cpp/digest/md5/md5.h
@@ -1,7 +1,5 @@
#pragma once
-#include <util/system/defaults.h>
-#include <util/generic/string.h>
#include <util/generic/array_ref.h>
#include <util/generic/strbuf.h>
@@ -16,26 +14,20 @@ public:
void Init();
inline MD5& Update(const void* data, size_t len) {
- const char* buf = (const char*)data;
-
- while (len) {
- // NOTE: we don't want buffSz to be near Max<unsigned int>()
- // because otherwise integer overflow might happen in UpdatePart
- const unsigned int buffSz = Min(size_t(Max<unsigned int>() / 2), len);
-
- UpdatePart(buf, buffSz);
- buf += buffSz;
- len -= buffSz;
- }
- return *this;
+ return Update(MakeArrayRef(static_cast<const ui8*>(data), len));
}
- inline MD5& Update(const TStringBuf& data) {
+ inline MD5& Update(TStringBuf data) {
return Update(data.data(), data.size());
}
+ inline MD5& Update(const TArrayRef<const ui8> data) {
+ UpdatePart(data);
+ return *this;
+ }
+
void Pad();
- unsigned char* Final(unsigned char[16]);
+ ui8* Final(ui8[16]);
// buf must be char[33];
char* End(char* buf);
@@ -57,23 +49,29 @@ public:
static TString File(const TString& filename);
static char* Data(const void* data, size_t len, char* buf);
- static TString Data(TArrayRef<ui8> data);
+ static char* Data(const TArrayRef<const ui8>& data, char* buf);
+ static TString Data(const TArrayRef<const ui8>& data);
static TString Data(TStringBuf data);
static char* Stream(IInputStream* in, char* buf);
- static TString Calc(const TStringBuf& data); // 32-byte hex-encoded
- static TString CalcRaw(const TStringBuf& data); // 16-byte raw
+ static TString Calc(TStringBuf data); // 32-byte hex-encoded
+ static TString Calc(const TArrayRef<const ui8>& data); // 32-byte hex-encoded
+ static TString CalcRaw(TStringBuf data); // 16-byte raw
+ static TString CalcRaw(const TArrayRef<const ui8>& data); // 16-byte raw
- static ui64 CalcHalfMix(const TStringBuf& data);
+ static ui64 CalcHalfMix(TStringBuf data);
+ static ui64 CalcHalfMix(const TArrayRef<const ui8>& data);
static ui64 CalcHalfMix(const char* data, size_t len);
- static bool IsMD5(const TStringBuf& data);
+ static bool IsMD5(TStringBuf data);
+ static bool IsMD5(const TArrayRef<const ui8>& data);
private:
- void UpdatePart(const void* data, unsigned int len);
+ void UpdatePart(TArrayRef<const ui8> data);
private:
- ui32 State[4]; /* state (ABCD) */
- ui32 Count[2]; /* number of bits, modulo 2^64 (lsb first) */
- unsigned char Buffer[64]; /* input buffer */
+ ui8 BufferSize; /* size of buffer */
+ ui8 Buffer[64]; /* input buffer */
+ ui32 State[4]; /* state (ABCD) */
+ ui64 StreamSize; /* total bytes in input stream */
};
diff --git a/library/cpp/digest/md5/md5_ut.cpp b/library/cpp/digest/md5/md5_ut.cpp
index fecccca9ba..1c3e4ad0a9 100644
--- a/library/cpp/digest/md5/md5_ut.cpp
+++ b/library/cpp/digest/md5/md5_ut.cpp
@@ -18,11 +18,11 @@ Y_UNIT_TEST_SUITE(TMD5Test) {
TString s(r.End(rs));
s.to_lower();
- UNIT_ASSERT_EQUAL(s, TStringBuf("3ac00dd696b966fd74deee3c35a59d8f"));
+ UNIT_ASSERT_NO_DIFF(s, TStringBuf("3ac00dd696b966fd74deee3c35a59d8f"));
TString result = r.Calc(TStringBuf(b));
result.to_lower();
- UNIT_ASSERT_EQUAL(result, TStringBuf("3ac00dd696b966fd74deee3c35a59d8f"));
+ UNIT_ASSERT_NO_DIFF(result, TStringBuf("3ac00dd696b966fd74deee3c35a59d8f"));
}
Y_UNIT_TEST(TestFile) {
@@ -39,10 +39,10 @@ Y_UNIT_TEST_SUITE(TMD5Test) {
TString fileHash = MD5::File(tmpFile.data(), fileBuf);
TString memoryHash = MD5::Data((const unsigned char*)s.data(), s.size(), memBuf);
- UNIT_ASSERT_EQUAL(fileHash, memoryHash);
+ UNIT_ASSERT_NO_DIFF(fileHash, memoryHash);
fileHash = MD5::File(tmpFile);
- UNIT_ASSERT_EQUAL(fileHash, memoryHash);
+ UNIT_ASSERT_NO_DIFF(fileHash, memoryHash);
NFs::Remove(tmpFile);
fileHash = MD5::File(tmpFile);
diff --git a/library/cpp/testing/unittest/registar.h b/library/cpp/testing/unittest/registar.h
index 332485bdf3..44517a0092 100644
--- a/library/cpp/testing/unittest/registar.h
+++ b/library/cpp/testing/unittest/registar.h
@@ -627,6 +627,23 @@ public: \
// Assert that a specific exception is thrown
#define UNIT_ASSERT_EXCEPTION(A, E) UNIT_ASSERT_EXCEPTION_C(A, E, "")
+#define UNIT_ASSERT_NO_EXCEPTION_RESULT_C(A, C) \
+ [&] () mutable -> decltype(A) { \
+ static_assert(!std::is_void_v<decltype(A)>); \
+ try { return (A); } \
+ catch (const ::NUnitTest::TAssertException&) { throw; } \
+ catch (...) { \
+ UNIT_FAIL_IMPL( \
+ "exception-free assertion failed", \
+ Sprintf("%s throws %s\nException message: %s", \
+ #A, (::TStringBuilder() << C).data(), \
+ CurrentExceptionMessage().data())); \
+ return decltype(A){}; \
+ } \
+ }()
+
+#define UNIT_ASSERT_NO_EXCEPTION_RESULT(A) UNIT_ASSERT_NO_EXCEPTION_RESULT_C(A, "")
+
#define UNIT_ASSERT_NO_EXCEPTION_C(A, C) \
do { \
try { \
diff --git a/library/cpp/testing/unittest/registar_ut.cpp b/library/cpp/testing/unittest/registar_ut.cpp
index aada471030..1f36d53abb 100644
--- a/library/cpp/testing/unittest/registar_ut.cpp
+++ b/library/cpp/testing/unittest/registar_ut.cpp
@@ -275,10 +275,22 @@ Y_UNIT_TEST_SUITE(TUnitTestMacroTest) {
}
}
+ std::string ThrowStr() {
+ if (ThrowMe) {
+ throw *this;
+ }
+
+ return {};
+ }
+
void AssertNoException() {
UNIT_ASSERT_NO_EXCEPTION(Throw());
}
+ void AssertNoExceptionRet() {
+ const TString res = UNIT_ASSERT_NO_EXCEPTION_RESULT(ThrowStr());
+ }
+
template <class TExpectedException>
void AssertException() {
UNIT_ASSERT_EXCEPTION(Throw(), TExpectedException);
@@ -333,6 +345,7 @@ Y_UNIT_TEST_SUITE(TUnitTestMacroTest) {
Y_UNIT_TEST(NoException) {
UNIT_ASSERT_TEST_FAILS(TTestException().AssertNoException());
+ UNIT_ASSERT_TEST_FAILS(TTestException().AssertNoExceptionRet());
UNIT_ASSERT_NO_EXCEPTION(TTestException("", false).Throw());
}