binary reader/writer: Increase limit of length-prefixed strings
So strings with a size up to 0xFFFFFFFFFFFFFF byte can be handled.
This commit is contained in:
parent
f4faf652fd
commit
1d4a4bd2be
|
@ -100,7 +100,7 @@ istream::pos_type BinaryReader::readStreamsize()
|
|||
*/
|
||||
string BinaryReader::readLengthPrefixedString()
|
||||
{
|
||||
static const int maxPrefixLength = 4;
|
||||
static constexpr int maxPrefixLength = 8;
|
||||
int prefixLength = 1;
|
||||
const byte beg = static_cast<byte>(m_stream->peek());
|
||||
byte mask = 0x80;
|
||||
|
@ -114,8 +114,7 @@ string BinaryReader::readLengthPrefixedString()
|
|||
memset(m_buffer, 0, maxPrefixLength);
|
||||
m_stream->read(m_buffer + (maxPrefixLength - prefixLength), prefixLength);
|
||||
*(m_buffer + (maxPrefixLength - prefixLength)) ^= mask;
|
||||
uint32 prefix = BE::toUInt32(m_buffer);
|
||||
return readString(prefix);
|
||||
return readString(BE::toUInt64(m_buffer));
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
|
@ -77,21 +77,18 @@ void BinaryWriter::setStream(ostream *stream, bool giveOwnership)
|
|||
*/
|
||||
void BinaryWriter::writeLengthPrefixedString(const string &value)
|
||||
{
|
||||
size_t length = value.length();
|
||||
if (length < 0x80) {
|
||||
m_buffer[0] = 0x80 | length;
|
||||
m_stream->write(m_buffer, 1);
|
||||
} else if (length < 0x4000) {
|
||||
BE::getBytes(static_cast<uint16>(0x4000 | length), m_buffer);
|
||||
m_stream->write(m_buffer, 2);
|
||||
} else if (length < 0x200000) {
|
||||
BE::getBytes(static_cast<uint32>(0x200000 | length), m_buffer);
|
||||
m_stream->write(m_buffer + 1, 3);
|
||||
} else if (length < 0x10000000) {
|
||||
BE::getBytes(static_cast<uint32>(0x10000000 | length), m_buffer);
|
||||
m_stream->write(m_buffer, 4);
|
||||
} else {
|
||||
const uint64 size = value.size();
|
||||
uint64 boundCheck = 0x80;
|
||||
byte prefixLength = 1;
|
||||
for (; boundCheck != 0x8000000000000000; boundCheck <<= 7, ++prefixLength) {
|
||||
if (size < boundCheck) {
|
||||
BE::getBytes(size | boundCheck, m_buffer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (prefixLength == 9) {
|
||||
throw ConversionException("The size of the string exceeds the maximum.");
|
||||
}
|
||||
m_stream->write(value.c_str(), length);
|
||||
m_stream->write(m_buffer + 8 - prefixLength, prefixLength);
|
||||
m_stream->write(value.data(), static_cast<streamsize>(size));
|
||||
}
|
||||
|
|
Binary file not shown.
|
@ -1,5 +1,6 @@
|
|||
#include "./testutils.h"
|
||||
|
||||
#include "../conversion/conversionexception.h"
|
||||
#include "../io/binaryreader.h"
|
||||
#include "../io/binarywriter.h"
|
||||
#include "../io/bitreader.h"
|
||||
|
@ -20,6 +21,7 @@ using namespace std;
|
|||
using namespace IoUtilities;
|
||||
using namespace TestUtilities;
|
||||
using namespace TestUtilities::Literals;
|
||||
using namespace ConversionUtilities;
|
||||
|
||||
using namespace CPPUNIT_NS;
|
||||
|
||||
|
@ -98,7 +100,7 @@ void IoTests::testBinaryReader()
|
|||
testFile.exceptions(ios_base::failbit | ios_base::badbit);
|
||||
testFile.open(TestUtilities::testFilePath("some_data"), ios_base::in | ios_base::binary);
|
||||
BinaryReader reader(&testFile);
|
||||
CPPUNIT_ASSERT_EQUAL(reader.readStreamsize(), static_cast<istream::pos_type>(95));
|
||||
CPPUNIT_ASSERT_EQUAL(reader.readStreamsize(), static_cast<istream::pos_type>(398));
|
||||
CPPUNIT_ASSERT(reader.readUInt16LE() == 0x0102u);
|
||||
CPPUNIT_ASSERT(reader.readUInt16BE() == 0x0102u);
|
||||
CPPUNIT_ASSERT(reader.readUInt24LE() == 0x010203u);
|
||||
|
@ -132,7 +134,14 @@ void IoTests::testBinaryReader()
|
|||
CPPUNIT_ASSERT(reader.readBool() == true);
|
||||
CPPUNIT_ASSERT(reader.readString(3) == "abc");
|
||||
CPPUNIT_ASSERT(reader.readLengthPrefixedString() == "ABC");
|
||||
CPPUNIT_ASSERT(reader.readLengthPrefixedString() == "01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901"
|
||||
"23456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123"
|
||||
"45678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345"
|
||||
"678901234567890123456789");
|
||||
CPPUNIT_ASSERT(reader.readTerminatedString() == "def");
|
||||
CPPUNIT_ASSERT_THROW(reader.readLengthPrefixedString(), ConversionException);
|
||||
CPPUNIT_ASSERT_MESSAGE("pos in stream not advanced on conversion error", reader.readByte() == 0);
|
||||
|
||||
// test ownership
|
||||
reader.setStream(nullptr, true);
|
||||
reader.setStream(new fstream(), true);
|
||||
|
@ -156,7 +165,7 @@ void IoTests::testBinaryWriter()
|
|||
// prepare output stream
|
||||
stringstream outputStream(ios_base::in | ios_base::out | ios_base::binary);
|
||||
outputStream.exceptions(ios_base::failbit | ios_base::badbit);
|
||||
char testData[95];
|
||||
char testData[397];
|
||||
outputStream.rdbuf()->pubsetbuf(testData, sizeof(testData));
|
||||
|
||||
// write test data
|
||||
|
@ -205,6 +214,9 @@ void IoTests::testBinaryWriter()
|
|||
writer.writeBool(true);
|
||||
writer.writeString("abc");
|
||||
writer.writeLengthPrefixedString("ABC");
|
||||
writer.writeLengthPrefixedString("012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"
|
||||
"123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901"
|
||||
"234567890123456789012345678901234567890123456789012345678901234567890123456789");
|
||||
writer.writeTerminatedString("def");
|
||||
|
||||
// test written values
|
||||
|
|
Loading…
Reference in New Issue