diff --git a/llvm/include/llvm/Support/MD5.h b/llvm/include/llvm/Support/MD5.h --- a/llvm/include/llvm/Support/MD5.h +++ b/llvm/include/llvm/Support/MD5.h @@ -78,6 +78,14 @@ /// Finishes off the hash and puts the result in result. void final(MD5Result &Result); + /// Finishes off the hash, and returns a reference to the 16-byte hash data. + StringRef final(); + + /// Finishes off the hash, and returns a reference to the 16-byte hash data. + /// This is suitable for getting the MD5 at any time without invalidating the + /// internal state, so that more calls can be made into `update`. + StringRef result(); + /// Translates the bytes in \p Res to a hex string that is /// deposited into \p Str. The result will be of length 32. static void stringifyResult(MD5Result &Result, SmallString<32> &Str); @@ -101,6 +109,8 @@ MD5_u32plus block[16]; } InternalState; + MD5Result Result; + const uint8_t *body(ArrayRef Data); }; diff --git a/llvm/lib/Support/MD5.cpp b/llvm/lib/Support/MD5.cpp --- a/llvm/lib/Support/MD5.cpp +++ b/llvm/lib/Support/MD5.cpp @@ -262,6 +262,23 @@ support::endian::write32le(&Result[12], InternalState.d); } +StringRef MD5::final() { + final(Result); + return StringRef(reinterpret_cast(Result.Bytes.data()), + Result.Bytes.size()); +} + +StringRef MD5::result() { + auto StateToRestore = InternalState; + + auto Hash = final(); + + // Restore the state + InternalState = StateToRestore; + + return Hash; +} + SmallString<32> MD5::MD5Result::digest() const { SmallString<32> Str; raw_svector_ostream Res(Str); diff --git a/llvm/unittests/Support/MD5Test.cpp b/llvm/unittests/Support/MD5Test.cpp --- a/llvm/unittests/Support/MD5Test.cpp +++ b/llvm/unittests/Support/MD5Test.cpp @@ -68,4 +68,35 @@ EXPECT_EQ(0x3be167ca6c49fb7dULL, MD5Res.high()); EXPECT_EQ(0x00e49261d7d3fcc3ULL, MD5Res.low()); } + +TEST(MD5Test, FinalAndResultHelpers) { + MD5 Hash; + + Hash.update("abcd"); + + { + MD5 ReferenceHash; + ReferenceHash.update("abcd"); + MD5::MD5Result ReferenceResult; + ReferenceHash.final(ReferenceResult); + StringRef ExpectedResult = + StringRef(reinterpret_cast(ReferenceResult.Bytes.data()), + ReferenceResult.Bytes.size()); + EXPECT_EQ(Hash.result(), ExpectedResult); + } + + Hash.update("xyz"); + + { + MD5 ReferenceHash; + ReferenceHash.update("abcd"); + ReferenceHash.update("xyz"); + MD5::MD5Result ReferenceResult; + ReferenceHash.final(ReferenceResult); + StringRef ExpectedResult = + StringRef(reinterpret_cast(ReferenceResult.Bytes.data()), + ReferenceResult.Bytes.size()); + EXPECT_EQ(Hash.final(), ExpectedResult); + } } +} // namespace