2014-06-05 16:44:12 +00:00
|
|
|
#include <DB/IO/HashingWriteBuffer.h>
|
2014-06-05 16:59:30 +00:00
|
|
|
#include <iomanip>
|
2017-01-16 19:47:11 +00:00
|
|
|
#include <city.h>
|
|
|
|
|
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
|
2017-03-25 20:12:56 +00:00
|
|
|
/// computation of the hash depends on the partitioning of blocks
|
|
|
|
/// so you need to compute a hash of n complete pieces and one incomplete
|
2017-01-16 19:47:11 +00:00
|
|
|
template <class Buffer>
|
|
|
|
void IHashingBuffer<Buffer>::calculateHash(DB::BufferBase::Position data, size_t len)
|
|
|
|
{
|
|
|
|
if (len)
|
|
|
|
{
|
2017-03-26 01:28:07 +00:00
|
|
|
/// if the data is less than `block_size`, then put them into buffer and calculate hash later
|
2017-01-16 19:47:11 +00:00
|
|
|
if (block_pos + len < block_size)
|
|
|
|
{
|
|
|
|
memcpy(&BufferWithOwnMemory<Buffer>::memory[block_pos], data, len);
|
|
|
|
block_pos += len;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-03-26 01:28:07 +00:00
|
|
|
/// if something is already written to the buffer, then we'll add it
|
2017-01-16 19:47:11 +00:00
|
|
|
if (block_pos)
|
|
|
|
{
|
|
|
|
size_t n = block_size - block_pos;
|
|
|
|
memcpy(&BufferWithOwnMemory<Buffer>::memory[block_pos], data, n);
|
|
|
|
append(&BufferWithOwnMemory<Buffer>::memory[0]);
|
|
|
|
len -= n;
|
|
|
|
data += n;
|
|
|
|
block_pos = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (len >= block_size)
|
|
|
|
{
|
|
|
|
append(data);
|
|
|
|
len -= block_size;
|
|
|
|
data += block_size;
|
|
|
|
}
|
|
|
|
|
2017-03-26 01:28:07 +00:00
|
|
|
/// write the remainder to its buffer
|
2017-01-16 19:47:11 +00:00
|
|
|
if (len)
|
|
|
|
{
|
|
|
|
memcpy(&BufferWithOwnMemory<Buffer>::memory[0], data, len);
|
|
|
|
block_pos = len;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template class IHashingBuffer<DB::ReadBuffer>;
|
|
|
|
template class IHashingBuffer<DB::WriteBuffer>;
|
|
|
|
|
|
|
|
}
|
2014-06-05 16:44:12 +00:00
|
|
|
|
2017-03-25 20:12:56 +00:00
|
|
|
/// UInt64 is 39 characters in 10th number system
|
2014-06-06 09:17:26 +00:00
|
|
|
static const size_t UINT64_DECIMAL_SIZE = 39;
|
|
|
|
std::string uint128ToString(uint128 data)
|
|
|
|
{
|
|
|
|
std::stringstream ss;
|
|
|
|
ss << std::setw(UINT64_DECIMAL_SIZE) << std::setfill('0') << data.first << std::setw(UINT64_DECIMAL_SIZE) << std::setfill('0') << data.second;
|
|
|
|
return ss.str();
|
|
|
|
}
|
|
|
|
|
2014-06-05 16:44:12 +00:00
|
|
|
std::ostream & operator<<(std::ostream & os, const uint128 & data)
|
|
|
|
{
|
2014-06-06 09:17:26 +00:00
|
|
|
os << uint128ToString(data);
|
2014-06-05 16:44:12 +00:00
|
|
|
return os;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::istream & operator>>(std::istream & is, uint128 & data)
|
|
|
|
{
|
2014-06-06 09:17:26 +00:00
|
|
|
std::vector<char> buffer(UINT64_DECIMAL_SIZE);
|
|
|
|
is.read(buffer.data(), UINT64_DECIMAL_SIZE);
|
|
|
|
data.first = DB::parse<UInt64>(buffer.data(), UINT64_DECIMAL_SIZE);
|
2014-06-05 16:44:12 +00:00
|
|
|
|
|
|
|
if (!is)
|
|
|
|
throw DB::Exception(std::string("Fail to parse uint128 from ") + buffer.data());
|
|
|
|
|
2014-06-06 09:17:26 +00:00
|
|
|
is.read(buffer.data(), UINT64_DECIMAL_SIZE);
|
|
|
|
data.first = DB::parse<UInt64>(buffer.data(), UINT64_DECIMAL_SIZE);
|
2014-06-05 16:44:12 +00:00
|
|
|
|
|
|
|
if (!is)
|
|
|
|
throw DB::Exception(std::string("Fail to parse uint128 from ") + buffer.data());
|
|
|
|
|
|
|
|
return is;
|
|
|
|
}
|