osrm-backend/include/util/connectivity_checksum.hpp
2022-12-20 18:00:11 +01:00

88 lines
1.9 KiB
C++

#ifndef CONNECTIVITY_CHECKSUM_HPP
#define CONNECTIVITY_CHECKSUM_HPP
#include <zlib.h>
#include <boost/assert.hpp>
#include <array>
#include <climits>
#include <cstdint>
namespace osrm::util
{
struct ConnectivityChecksum
{
ConnectivityChecksum() : checksum(0), length(0), byte_number(0), bit_number(0) {}
void process_byte(unsigned char byte)
{
BOOST_ASSERT(byte_number < buffer.size());
if (bit_number > 0)
{
bit_number = 0;
++byte_number;
++length;
}
flush_bytes();
buffer[byte_number] = byte;
++byte_number;
++length;
flush_bytes();
buffer[byte_number] = 0;
}
void process_bit(bool bit)
{
BOOST_ASSERT(byte_number < buffer.size());
BOOST_ASSERT(bit_number < CHAR_BIT);
buffer[byte_number] = (buffer[byte_number] << 1) | static_cast<unsigned char>(bit);
if (++bit_number >= CHAR_BIT)
{
bit_number = 0;
++byte_number;
++length;
flush_bytes();
buffer[byte_number] = 0;
}
}
std::uint32_t update_checksum(std::uint32_t current)
{
if (bit_number > 0)
{
++byte_number;
++length;
}
checksum = crc32(checksum, buffer.data(), byte_number);
checksum = crc32_combine(current, checksum, length);
length = byte_number = bit_number = 0;
buffer[byte_number] = 0;
return checksum;
}
private:
void flush_bytes()
{
if (byte_number >= buffer.size())
{
checksum = crc32(checksum, buffer.data(), buffer.size());
byte_number = 0;
}
}
std::array<unsigned char, 64> buffer;
std::uint32_t checksum;
std::size_t length;
std::size_t byte_number;
unsigned char bit_number;
};
} // namespace osrm::util
#endif