use VarInt
All checks were successful
Linux arm64 / Build (push) Successful in 12m53s

This commit is contained in:
2025-06-12 21:38:47 +02:00
parent 3e40ff7252
commit 17459c4026
5 changed files with 111 additions and 27 deletions

View File

@@ -1,5 +1,7 @@
#include "Compression.h" #include "Compression.h"
#include "VarInt.h"
#include <cassert> #include <cassert>
#include <zlib.h> #include <zlib.h>
@@ -33,10 +35,7 @@ DataBuffer Compress(const DataBuffer& buffer) {
if (buffer.GetSize() < COMPRESSION_THRESHOLD) { if (buffer.GetSize() < COMPRESSION_THRESHOLD) {
// Don't compress since it's a small packet // Don't compress since it's a small packet
std::uint64_t compressedDataLength = 0; VarInt compressedDataLength = 0;
std::uint64_t packetLength = compressedDataLength + buffer.GetSize();
packet << packetLength;
packet << compressedDataLength; packet << compressedDataLength;
packet << buffer; packet << buffer;
return packet; return packet;
@@ -44,22 +43,19 @@ DataBuffer Compress(const DataBuffer& buffer) {
DataBuffer compressedData = Deflate(buffer.data(), buffer.GetSize()); DataBuffer compressedData = Deflate(buffer.data(), buffer.GetSize());
std::uint64_t uncompressedDataLength = buffer.GetSize(); VarInt uncompressedDataLength = buffer.GetSize();
std::uint64_t packetLength = uncompressedDataLength + compressedData.GetSize();
packet << packetLength;
packet << uncompressedDataLength; packet << uncompressedDataLength;
packet.WriteSome(compressedData.data(), compressedData.GetSize()); packet.WriteSome(compressedData.data(), compressedData.GetSize());
return packet; return packet;
} }
DataBuffer Decompress(DataBuffer& buffer, std::uint64_t packetLength) { DataBuffer Decompress(DataBuffer& buffer, std::uint64_t packetLength) {
std::uint64_t uncompressedLength; VarInt uncompressedLength;
buffer >> uncompressedLength; buffer >> uncompressedLength;
std::uint64_t compressedLength = packetLength - uncompressedLength; std::uint64_t compressedLength = packetLength - uncompressedLength.GetSerializedLength();
if (uncompressedLength == 0) { if (uncompressedLength.GetValue() == 0) {
// Data already uncompressed. Nothing to do // Data already uncompressed. Nothing to do
DataBuffer ret; DataBuffer ret;
buffer.ReadSome(ret, compressedLength); buffer.ReadSome(ret, compressedLength);
@@ -68,12 +64,5 @@ DataBuffer Decompress(DataBuffer& buffer, std::uint64_t packetLength) {
assert(buffer.GetReadOffset() + compressedLength <= buffer.GetSize()); assert(buffer.GetReadOffset() + compressedLength <= buffer.GetSize());
return Inflate(buffer.data() + buffer.GetReadOffset(), compressedLength, uncompressedLength); return Inflate(buffer.data() + buffer.GetReadOffset(), compressedLength, uncompressedLength.GetValue());
}
DataBuffer Decompress(DataBuffer& buffer) {
std::uint64_t packetLength;
buffer >> packetLength;
return Decompress(buffer, packetLength);
} }

View File

@@ -14,13 +14,6 @@
*/ */
DataBuffer Compress(const DataBuffer& buffer); DataBuffer Compress(const DataBuffer& buffer);
/**
* \brief Reads the packet lenght and uncompress it
* \param buffer the data to uncompress
* \return the uncompressed data
*/
DataBuffer Decompress(DataBuffer& buffer);
/** /**
* \brief Uncompress some data * \brief Uncompress some data
* \param buffer the data to uncompress * \param buffer the data to uncompress

48
src/Common/VarInt.cpp Normal file
View File

@@ -0,0 +1,48 @@
#include "VarInt.h"
#include "DataBuffer.h"
#include <stdexcept>
static constexpr int SEGMENT_BITS = 0x7F;
static constexpr int CONTINUE_BIT = 0x80;
std::size_t VarInt::GetSerializedLength() const {
DataBuffer buffer;
buffer << *this;
return buffer.GetSize();
}
DataBuffer& operator<<(DataBuffer& out, const VarInt& var) {
std::uint64_t value = var.m_Value;
while (true) {
if ((value & ~static_cast<std::uint64_t>(SEGMENT_BITS)) == 0) {
out << static_cast<std::uint8_t>(value);
return out;
}
out << static_cast<std::uint8_t>((value & SEGMENT_BITS) | CONTINUE_BIT);
value >>= 7;
}
}
DataBuffer& operator>>(DataBuffer& in, VarInt& var) {
var.m_Value = 0;
unsigned int position = 0;
std::uint8_t currentByte;
while (true) {
in.ReadSome(&currentByte, 1);
var.m_Value |= static_cast<std::uint64_t>(currentByte & SEGMENT_BITS) << position;
if ((currentByte & CONTINUE_BIT) == 0)
break;
position += 7;
if (position >= 8 * sizeof(var.m_Value))
throw std::runtime_error("VarInt is too big");
}
return in;
}

54
src/Common/VarInt.h Normal file
View File

@@ -0,0 +1,54 @@
#pragma once
/**
* \file VarInt.h
* \brief File containing the blitz::VarInt class
*/
#include <cstddef>
#include <cstdint>
class DataBuffer;
/**
* \class VarInt
* \brief Variable-length format such that smaller numbers use fewer bytes.
*/
class VarInt {
private:
std::uint64_t m_Value;
public:
VarInt() : m_Value(0) {}
/**
* \brief Construct a variable integer from a value
* \param value The value of the variable integer
*/
VarInt(std::uint64_t value) : m_Value(value) {}
/**
* \brief Get the value of the variable integer
*/
std::uint64_t GetValue() const {
return m_Value;
}
/**
* \brief Get the length of the serialized variable integer
*/
std::size_t GetSerializedLength() const;
/**
* \brief Serialize the variable integer
* \param out The buffer to write the serialized variable integer to
* \param var The variable integer to serialize
*/
friend DataBuffer& operator<<(DataBuffer& out, const VarInt& var);
/**
* \brief Deserialize the variable integer
* \param in The buffer to read the serialized variable integer from
* \param var The variable integer to deserialize
*/
friend DataBuffer& operator>>(DataBuffer& in, VarInt& var);
};

View File

@@ -73,7 +73,7 @@ bool PiecesFiles::loadPieces(int polyominoSize, std::vector<Piece>& pieces, std:
if(!compressed.ReadFile(filePath)) if(!compressed.ReadFile(filePath))
return false; return false;
DataBuffer buffer = Decompress(compressed); DataBuffer buffer = Decompress(compressed, compressed.GetSize());
std::ifstream piecesFile(filePath, std::ios::binary); std::ifstream piecesFile(filePath, std::ios::binary);
if (!piecesFile.good()) { if (!piecesFile.good()) {