32#include "rawspeedconfig.h"
88 std::variant<NoBuffer, FullBufferRef, CoalescingBuffer>
state =
NoBuffer();
91 template <
typename ArgTy>
96 template <
typename ArgTy>
97 requires std::same_as<ArgTy, NoBuffer>
102 if (message.
size() == N) {
112 template <
typename ArgTy>
113 requires std::same_as<ArgTy, CoalescingBuffer>
124 std::copy(message.
begin(), message.
end(), out.begin());
129 return std::visit([](
const auto& arg) {
return arg.block_length; },
state);
134 bytesAvaliable() const noexcept {
139 return bytesAvaliable() == N;
143 return bytesAvaliable() == 0;
154 [
this, message]<
typename T>(
T& arg) {
155 if constexpr (std::is_same_v<T, FullBufferRef>)
156 __builtin_unreachable();
166 if constexpr (std::is_same_v<T, FullBufferRef>)
168 else if constexpr (std::is_same_v<T, CoalescingBuffer>) {
170 return {{arg.block.data(), arg.block_length}};
171 }
else if constexpr (std::is_same_v<T, NoBuffer>) {
172 __builtin_unreachable();
188 {UINT32_C(0x67452301), UINT32_C(0xEFCDAB89), UINT32_C(0x98BADCFE),
189 UINT32_C(0x10325476)}};
198 return buffer.bytesAvaliable();
202 return buffer.blockIsEmpty();
205 [[nodiscard]]
bool blockIsFull() const noexcept RAWSPEED_READONLY {
206 return buffer.blockIsFull();
211 template <typename
T>
212 requires std::is_same_v<
T, uint8_t>
213 MD5& operator<<(const
T& v) noexcept;
215 template <typename
T>
216 requires std::is_same_v<
T, uint8_t>
219 template <typename
T>
220 requires std::is_same_v<
T, uint8_t>
232 template <typename
T>
233 requires std::is_same_v<
T, uint8_t>
239__attribute__((always_inline)) inline
void MD5::compressFullBlock() noexcept {
242 const auto fullBlock =
buffer.getAsFullBufferRef();
244 state, {fullBlock.block,
decltype(fullBlock)::block_length});
249 requires std::is_same_v<T, uint8_t>
255 invariant(message.size() <= bytesAvaliableInBlock());
257 buffer.take_block(message);
258 bytes_total += message.size();
264 requires std::is_same_v<T, uint8_t>
269 invariant(message.size() == MD5Hasher::block_size);
278 requires std::is_same_v<T, uint8_t>
279__attribute__((always_inline))
inline MD5& MD5::take(
const T* message,
280 size_t len)
noexcept {
289 if (!blockIsEmpty()) {
291 std::min<size_t>(msg.size(), bytesAvaliableInBlock()));
293 msg.getCrop(0, prefix_size).getAsArray1DRef();
294 msg = msg.getCrop(prefixMsg.size(), msg.size() - prefixMsg.size())
296 take_block(prefixMsg);
305 msg.size() / MD5Hasher::block_size);
306 for (
int blockIdx = 0; blockIdx != numFullBlocks; ++blockIdx) {
307 auto innerMsg =
msg.getCrop(0, MD5Hasher::block_size)
309 msg =
msg.getCrop(innerMsg.size(),
msg.size() - innerMsg.size())
311 take_full_block(innerMsg);
315 if (
msg.size() > 0) {
326MD5::flush() noexcept {
329 static constexpr std::array<uint8_t, 1> magic0 = {0x80};
330 buffer.take_block({magic0.data(), magic0.size()});
332 static constexpr std::array<uint8_t, MD5Hasher::block_size> zeropadding = {};
333 if (bytesAvaliableInBlock() < 8) {
334 if (bytesAvaliableInBlock() > 0)
335 buffer.take_block({zeropadding.data(), bytesAvaliableInBlock()});
339 if (bytesAvaliableInBlock() > 8)
340 buffer.take_block({zeropadding.data(), bytesAvaliableInBlock() - 8});
342 std::array<uint8_t, 8> magic1;
343 magic1[0] =
static_cast<uint8_t
>((bytes_total & 0x1FU) << 3);
345 for (
size_t i = 1; i < 8; i++) {
346 magic1[i] =
static_cast<uint8_t
>(bytes_total);
349 buffer.take_block({magic1.data(), magic1.size()});
352 MD5Hasher::state_type tmp = state;
358[[nodiscard]] MD5Hasher::state_type md5_hash(
const uint8_t* message,
359 size_t len)
noexcept;
362[[nodiscard]] std::string
bool RAWSPEED_READNONE __attribute__((visibility("default"))) benchmarkDryRun()
int RAWSPEED_READONLY size() const
void take_block_impl(NoBuffer &, Array1DRef< const uint8_t > message)
__attribute__((always_inline)) int bytesAvaliable() const noexcept
bool blockIsFull() const noexcept
void take_block_impl(CoalescingBuffer &arg, Array1DRef< const uint8_t > message) const
bool blockIsEmpty() const noexcept
FullBufferRef getAsFullBufferRef() const
std::variant< NoBuffer, FullBufferRef, CoalescingBuffer > state
void take_block_impl(ArgTy &arg, Array1DRef< const uint8_t > message) const =delete
__attribute__((always_inline)) void take_block(Array1DRef< const uint8_t > message) noexcept
__attribute__((always_inline)) int length() const noexcept
MD5Hasher() noexcept=delete
std::array< uint8_t, block_size > block_type
static state_type compress(state_type state, Array1DRef< const uint8_t > block) noexcept
std::array< uint32_t, 4 > state_type
static constexpr int block_size
bool blockIsEmpty() const noexcept RAWSPEED_READONLY
MD5Hasher::state_type state
MD5Hasher::state_type flush() noexcept
MD5(MD5 &&) noexcept=delete
static constexpr const MD5Hasher::state_type md5_init
BufferCoalescer< MD5Hasher::block_size > buffer
MD5 & take_full_block(Array1DRef< const T > message) noexcept
MD5 & take(const T *message, size_t len) noexcept
bool blockIsFull() const noexcept RAWSPEED_READONLY
MD5 & take_block(Array1DRef< const T > message) noexcept
__attribute__((always_inline)) inline void compressFullBlock() noexcept
int bytesAvaliableInBlock() const noexcept RAWSPEED_READONLY
__attribute__((always_inline)) inline void MD5 std::string hash_to_string(const MD5Hasher::state_type &hash) noexcept
constexpr bool always_false_v
constexpr RAWSPEED_READNONE Ttgt implicit_cast(Tsrc value)
void RAWSPEED_UNLIKELY_FUNCTION RAWSPEED_NOINLINE static char buf[bufSize]
Array1DRef(T *data_, int numElts_) -> Array1DRef< T >
constexpr RAWSPEED_READNONE Ttgt implicit_cast(Tsrc value)
MD5Hasher::block_type block
static constexpr int block_length
FullBufferRef(Array1DRef< const uint8_t > block_)
static constexpr int block_length