2018-10-01 22:22:11 +02:00
|
|
|
#pragma once
|
|
|
|
#include "Streams.h"
|
|
|
|
#include "LEB128.h"
|
|
|
|
#include "ChunkId.h"
|
|
|
|
|
|
|
|
typedef struct ChunkWritingState
|
|
|
|
{
|
|
|
|
private:
|
|
|
|
BaseStream* m_stream;
|
|
|
|
__int64 m_chunkSizePosition;
|
|
|
|
__int64 m_previousPosition;
|
|
|
|
__int64 m_maximumSize;
|
|
|
|
|
|
|
|
public:
|
|
|
|
ChunkWritingState(BaseStream* stream, ChunkId* chunkID, __int64 maximumSize)
|
|
|
|
{
|
|
|
|
m_stream = stream;
|
|
|
|
|
|
|
|
// Write chunk ID
|
|
|
|
chunkID->ToStream(m_stream);
|
|
|
|
|
|
|
|
// Write chunk size
|
|
|
|
m_chunkSizePosition = m_stream->GetCurrentPosition();
|
|
|
|
LEB128::Write(m_stream, 0, maximumSize);
|
|
|
|
|
|
|
|
// Prepare for writeing chunk content
|
|
|
|
m_previousPosition = m_stream->GetCurrentPosition();
|
|
|
|
m_maximumSize = maximumSize;
|
|
|
|
}
|
|
|
|
|
|
|
|
void EndWrite()
|
|
|
|
{
|
|
|
|
// Update chunk size
|
|
|
|
long newPosition = m_stream->GetCurrentPosition();
|
|
|
|
long chunkSize = newPosition - m_previousPosition;
|
|
|
|
m_stream->Seek(m_chunkSizePosition, SEEK_ORIGIN::BEGIN);
|
|
|
|
LEB128::Write(m_stream, chunkSize, m_maximumSize);
|
|
|
|
m_stream->Seek(newPosition, SEEK_ORIGIN::BEGIN);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class ChunkWriter {
|
|
|
|
private:
|
|
|
|
BaseStream* m_stream;
|
|
|
|
|
|
|
|
public:
|
2019-12-02 09:11:21 +01:00
|
|
|
ChunkWriter(int magicNumber, BaseStream* stream)
|
2018-10-01 22:22:11 +02:00
|
|
|
{
|
|
|
|
m_stream = stream;
|
|
|
|
|
2018-10-10 22:29:40 +02:00
|
|
|
m_stream->WriteInt32(magicNumber);
|
|
|
|
m_stream->WriteInt32(0);
|
2018-10-01 22:22:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
BaseStream* GetRawStream()
|
|
|
|
{
|
|
|
|
return m_stream;
|
|
|
|
}
|
|
|
|
|
|
|
|
void WriteChunkEnd()
|
|
|
|
{
|
2018-10-10 22:29:40 +02:00
|
|
|
m_stream->WriteByte(0);
|
2018-10-01 22:22:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void WriteChunkEmpty(ChunkId* chunkID)
|
|
|
|
{
|
|
|
|
chunkID->ToStream(m_stream);
|
|
|
|
LEB128::Write(m_stream, 0);
|
|
|
|
}
|
|
|
|
|
2019-12-02 09:11:21 +01:00
|
|
|
void WriteChunkArrayOfBytes(ChunkId* chunkID, byte* value, int length)
|
2018-10-01 22:22:11 +02:00
|
|
|
{
|
|
|
|
chunkID->ToStream(m_stream);
|
|
|
|
LEB128::Write(m_stream, length);
|
|
|
|
m_stream->WriteBytes(value, length);
|
|
|
|
}
|
|
|
|
|
|
|
|
void WriteChunkInt(ChunkId* chunkID, __int64 value)
|
|
|
|
{
|
|
|
|
chunkID->ToStream(m_stream);
|
|
|
|
LEB128::Write(m_stream, LEB128::GetLength(m_stream, value));
|
|
|
|
LEB128::Write(m_stream, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
ChunkWritingState* WriteChunk(ChunkId* chunkID, __int64 maximumSize = LEB128::MaximumSize4Byte)
|
|
|
|
{
|
|
|
|
return new ChunkWritingState(m_stream, chunkID, maximumSize);
|
|
|
|
}
|
|
|
|
|
2019-12-02 09:11:21 +01:00
|
|
|
void WriteChunk(ChunkId* chunkID, void(*writeChunk)(int, int), int arg1, int arg2, __int64 maximumSize = LEB128::MaximumSize4Byte)
|
2018-10-01 22:22:11 +02:00
|
|
|
{
|
|
|
|
ChunkWritingState* state = WriteChunk(chunkID, maximumSize);
|
2018-10-24 23:32:22 +02:00
|
|
|
writeChunk(arg1, arg2);
|
2018-10-01 22:22:11 +02:00
|
|
|
state->EndWrite();
|
|
|
|
delete state;
|
|
|
|
}
|
|
|
|
|
2019-12-02 09:11:21 +01:00
|
|
|
void WriteChunkWithChildren(ChunkId* chunkID, void(*writeChunk)(int, int), int arg1, int arg2, __int64 maximumSize = LEB128::MaximumSize4Byte)
|
2018-10-01 22:22:11 +02:00
|
|
|
{
|
|
|
|
ChunkWritingState* state = WriteChunk(chunkID, maximumSize);
|
2018-10-24 23:32:22 +02:00
|
|
|
writeChunk(arg1, arg2);
|
2018-10-01 22:22:11 +02:00
|
|
|
WriteChunkEnd();
|
|
|
|
state->EndWrite();
|
|
|
|
delete state;
|
|
|
|
}
|
|
|
|
};
|