Files
DarkflameServer/dCommon/Sd0.h
Aaron Kimbrell 43cea3a245 fix: limit the chunks and the inflated size of an sd0 buffer
An sd0 buffer could hold any number of chunks, and each chunk grew the
inflated data by a full chunk whatever it held, so the data of a chunk
that was not full was followed by a gap. A buffer now holds at most
4096 chunks and inflates to at most 64 MiB, and every chunk is inflated
right after the one before it.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
2026-11-10 16:28:34 -06:00

64 lines
1.9 KiB
C++

// Darkflame Universe
// Copyright 2025
#ifndef SD0_H
#define SD0_H
#include <cstdint>
#include <fstream>
#include <sstream>
#include <string>
#include <string_view>
#include <vector>
// Sd0 is comprised of multiple zlib compressed buffers stored in a row.
// The format starts with a SD0 header (see SD0_HEADER) followed by the size of a zlib buffer, and then the zlib buffer itself.
// This repeats until end of file
class Sd0 {
public:
using BinaryBuffer = std::vector<uint8_t>;
static inline const char* SD0_HEADER = "sd0\x01\xff";
/**
* @brief Max size of an inflated sd0 zlib chunk
*/
static constexpr inline size_t MAX_UNCOMPRESSED_CHUNK_SIZE = 1024 * 256;
/**
* @brief Max number of zlib chunks in one sd0 buffer
*/
static constexpr inline uint32_t MAX_CHUNKS = 4096;
/**
* @brief Max size of an sd0 buffer once all of its chunks are inflated, far above the size of a model
*/
static constexpr inline uint32_t MAX_UNCOMPRESSED_SIZE = 64 * 1024 * 1024;
// Empty, for FromData
Sd0() = default;
// Read the input buffer into an internal chunk stream to be used later
Sd0(std::istream& buffer);
// `data` compressed into an sd0 buffer, returned in its raw compressed form (what the client reads, e.g. the UGC
// files it downloads without 3D services); only the header when `data` is empty, empty when it can't be compressed
[[nodiscard]] static std::string Compress(std::string_view data);
// Uncompresses the entire Sd0 buffer and returns it as a string
[[nodiscard]] std::string GetAsStringUncompressed() const;
// Gets the Sd0 buffer as a stream in its raw compressed form
[[nodiscard]] std::stringstream GetAsStream() const;
// Gets the Sd0 buffer as a vector in its raw compressed form
[[nodiscard]] const std::vector<BinaryBuffer>& GetAsVector() const;
// Compress data into a Sd0 buffer
void FromData(const uint8_t* data, size_t bufferSize);
private:
std::vector<BinaryBuffer> m_Chunks{};
};
#endif //!SD0_H