2016-08-29 15:35:48 +02:00
|
|
|
#include "./binarywriter.h"
|
|
|
|
|
|
|
|
#include "../conversion/conversionexception.h"
|
|
|
|
|
|
|
|
#include <cstring>
|
|
|
|
#include <memory>
|
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
using namespace IoUtilities;
|
|
|
|
using namespace ConversionUtilities;
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* \class IoUtilities::BinaryWriter
|
|
|
|
* \brief Writes primitive data types to a std::ostream.
|
|
|
|
* \remarks Supports both, little endian and big endian.
|
2018-05-31 23:26:38 +02:00
|
|
|
* \sa For automatic deserialization of structs, see https://github.com/Martchus/reflective-rapidjson.
|
2016-08-29 15:35:48 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* \brief Constructs a new BinaryWriter.
|
|
|
|
* \param stream Specifies the stream to write to.
|
|
|
|
*/
|
2017-05-01 03:13:11 +02:00
|
|
|
BinaryWriter::BinaryWriter(ostream *stream)
|
|
|
|
: m_stream(stream)
|
|
|
|
, m_ownership(false)
|
|
|
|
{
|
|
|
|
}
|
2016-08-29 15:35:48 +02:00
|
|
|
|
|
|
|
/*!
|
|
|
|
* \brief Copies the specified BinaryWriter.
|
|
|
|
* \remarks The copy will not take ownership over the stream.
|
|
|
|
*/
|
2017-05-01 03:13:11 +02:00
|
|
|
BinaryWriter::BinaryWriter(const BinaryWriter &other)
|
|
|
|
: m_stream(other.m_stream)
|
|
|
|
, m_ownership(false)
|
|
|
|
{
|
|
|
|
}
|
2016-08-29 15:35:48 +02:00
|
|
|
|
|
|
|
/*!
|
|
|
|
* \brief Destroys the BinaryWriter.
|
|
|
|
*/
|
|
|
|
BinaryWriter::~BinaryWriter()
|
|
|
|
{
|
2017-05-01 03:13:11 +02:00
|
|
|
if (m_ownership) {
|
2016-08-29 15:35:48 +02:00
|
|
|
delete m_stream;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* \brief Assigns the stream the writer will write to when calling one of the write-methods.
|
|
|
|
*
|
|
|
|
* You can assign a null pointer when ensuring that none of the write-methods is called
|
|
|
|
* until a stream is assigned.
|
|
|
|
*
|
|
|
|
* \param stream Specifies the stream to be assigned.
|
|
|
|
* \param giveOwnership Indicated whether the reader should take ownership (default is false).
|
|
|
|
*
|
|
|
|
* \sa setStream()
|
|
|
|
*/
|
|
|
|
void BinaryWriter::setStream(ostream *stream, bool giveOwnership)
|
|
|
|
{
|
2017-05-01 03:13:11 +02:00
|
|
|
if (m_ownership) {
|
2016-08-29 15:35:48 +02:00
|
|
|
delete m_stream;
|
|
|
|
}
|
2017-05-01 03:13:11 +02:00
|
|
|
if (stream) {
|
2016-08-29 15:35:48 +02:00
|
|
|
m_stream = stream;
|
|
|
|
m_ownership = giveOwnership;
|
|
|
|
} else {
|
|
|
|
m_stream = nullptr;
|
|
|
|
m_ownership = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
2018-05-31 23:26:38 +02:00
|
|
|
* \brief Writes the specified integer \a value. Conversion to bytes is done using the specified function.
|
2016-08-29 15:35:48 +02:00
|
|
|
*/
|
2018-05-31 23:26:38 +02:00
|
|
|
void BinaryWriter::writeVariableLengthInteger(uint64 value, void (*getBytes)(uint64, char *))
|
2016-08-29 15:35:48 +02:00
|
|
|
{
|
2017-07-28 20:34:50 +02:00
|
|
|
uint64 boundCheck = 0x80;
|
|
|
|
byte prefixLength = 1;
|
|
|
|
for (; boundCheck != 0x8000000000000000; boundCheck <<= 7, ++prefixLength) {
|
2018-05-31 23:26:38 +02:00
|
|
|
if (value < boundCheck) {
|
|
|
|
getBytes(value | boundCheck, m_buffer);
|
2017-07-28 20:34:50 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (prefixLength == 9) {
|
2018-05-31 23:26:38 +02:00
|
|
|
throw ConversionException("The variable-length integer to be written exceeds the maximum.");
|
2016-08-29 15:35:48 +02:00
|
|
|
}
|
2017-07-28 20:34:50 +02:00
|
|
|
m_stream->write(m_buffer + 8 - prefixLength, prefixLength);
|
2018-05-31 23:26:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* \brief Writes the length of a string and the string itself to the current stream.
|
|
|
|
*
|
|
|
|
* Advances the current position of the stream by the length of the string plus the size of the length prefix.
|
|
|
|
*
|
|
|
|
* \throws Throws ConversionException if the string size exceeds the maximum.
|
|
|
|
* \todo Make inline in v5.
|
|
|
|
*/
|
|
|
|
void BinaryWriter::writeLengthPrefixedString(const string &value)
|
|
|
|
{
|
|
|
|
writeVariableLengthUIntBE(value.size());
|
|
|
|
m_stream->write(value.data(), static_cast<streamsize>(value.size()));
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* \brief Writes the length of a string and the string itself to the current stream.
|
|
|
|
*
|
|
|
|
* Advances the current position of the stream by the length of the string plus the size of the length prefix.
|
|
|
|
*
|
|
|
|
* \throws Throws ConversionException if the string size exceeds the maximum.
|
|
|
|
* \todo Make inline in v5.
|
|
|
|
*/
|
|
|
|
void BinaryWriter::writeLengthPrefixedCString(const char *value, size_t size)
|
|
|
|
{
|
|
|
|
writeVariableLengthUIntBE(size);
|
|
|
|
m_stream->write(value, static_cast<streamsize>(size));
|
2016-08-29 15:35:48 +02:00
|
|
|
}
|