Yes, the idea is to manage memory yourself. SFML cannot know how you allocated it, especially since you're returning a void pointer.
"Manage yourself" means use RAII and store the data in a member variable that survives the onSend() call, not a local variable. In your case, a good choice for a buffer of bytes would be std::vector<Bytef>. Then you don't need the casts (which should have been rather reinterpret_cast than C casts, to state the danger explicitly in code and tell the compiler unambiguously what you want).
If you're interested in RAII and why it's a good idea to avoid new/delete, you could read my article.
Excellent, thanks for the response. The article is a good read.
This is one of the few instances I have used
new /
delete at all in this codebase - I've mostly been using
Object object; object.Method(); for my game objects, except where it has been unavoidable (and I'm going to change those to smart pointers having read that).
With regards to using a vector, I wasn't quite sure how I'd go about translating that to a
Bytef pointer, as zlib requires for these calls. I guess I might have to use
z_stream to feed zlib each byte at a time, but I'm not sure how I'd tackle that. I'd like to keep the solution simple.
So, for a non-leaking but still imperfect solution, I have:
class StreamSerialiser : public sf::Packet
{
...
private:
virtual const void* onSend(std::size_t& size);
virtual void onReceive(const void* data, std::size_t size);
Bytef m_oCompressionBuffer[1500];
Bytef m_oDecompressionBuffer[1500];
}
The compression portion:
const void* StreamSerialiser::onSend(std::size_t& size)
{
const Bytef* srcData = reinterpret_cast<const Bytef*>(getData());
uLong srcSize = getDataSize();
uLong dstSize = compressBound(srcSize);
compress(m_oCompressionBuffer, &dstSize, srcData, getDataSize());
size = dstSize;
return m_oCompressionBuffer;
}
The decompression portion:
void StreamSerialiser::onReceive(const void* data, std::size_t size)
{
const Bytef* srcData = reinterpret_cast<const Bytef*>(data);
uLong dstSize;
uncompress(m_oDecompressionBuffer, &dstSize, srcData, size);
append(m_oDecompressionBuffer, dstSize);
}
The obvious flaw here is that the buffers are only 1500 bytes, which suffices for usage with UDP packets, but makes this class very single-purpose. I perhaps could use only one buffer too - this class shouldn't need to be thread safe.
I agree a vector would be a better fit for this, but again I'm not sure how to implement that with the zlib calls.
Cheers!