mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-21 19:45:53 +00:00
Allow external buffers in MemoryOutputStream
This commit is contained in:
@@ -92,7 +92,7 @@ public:
|
|||||||
|
|
||||||
/** Reads a boolean from the stream.
|
/** Reads a boolean from the stream.
|
||||||
|
|
||||||
The bool is encoded as a single byte - 0 for false, nonzero for true.
|
The bool is encoded as a single byte - non-zero for true, 0 for false.
|
||||||
|
|
||||||
If the stream is exhausted, this will return false.
|
If the stream is exhausted, this will return false.
|
||||||
|
|
||||||
@@ -117,8 +117,7 @@ public:
|
|||||||
|
|
||||||
/** Reads two bytes from the stream as a little-endian 16-bit value.
|
/** Reads two bytes from the stream as a little-endian 16-bit value.
|
||||||
|
|
||||||
If the next two bytes read are byte1 and byte2, this returns
|
If the next two bytes read are byte1 and byte2, this returns (byte1 | (byte2 << 8)).
|
||||||
(byte2 | (byte1 << 8)).
|
|
||||||
|
|
||||||
If the stream is exhausted partway through reading the bytes, this will return zero.
|
If the stream is exhausted partway through reading the bytes, this will return zero.
|
||||||
|
|
||||||
|
|||||||
@@ -22,23 +22,28 @@
|
|||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
|
||||||
MemoryOutputStream::MemoryOutputStream (const size_t initialSize)
|
MemoryOutputStream::MemoryOutputStream (const size_t initialSize)
|
||||||
: data (internalBlock),
|
: blockToUse (&internalBlock), externalData (nullptr),
|
||||||
position (0),
|
position (0), size (0), availableSize (0)
|
||||||
size (0)
|
|
||||||
{
|
{
|
||||||
internalBlock.setSize (initialSize, false);
|
internalBlock.setSize (initialSize, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
MemoryOutputStream::MemoryOutputStream (MemoryBlock& memoryBlockToWriteTo,
|
MemoryOutputStream::MemoryOutputStream (MemoryBlock& memoryBlockToWriteTo,
|
||||||
const bool appendToExistingBlockContent)
|
const bool appendToExistingBlockContent)
|
||||||
: data (memoryBlockToWriteTo),
|
: blockToUse (&memoryBlockToWriteTo), externalData (nullptr),
|
||||||
position (0),
|
position (0), size (0), availableSize (0)
|
||||||
size (0)
|
|
||||||
{
|
{
|
||||||
if (appendToExistingBlockContent)
|
if (appendToExistingBlockContent)
|
||||||
position = size = memoryBlockToWriteTo.getSize();
|
position = size = memoryBlockToWriteTo.getSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MemoryOutputStream::MemoryOutputStream (void* destBuffer, size_t destBufferSize)
|
||||||
|
: blockToUse (nullptr), externalData (destBuffer),
|
||||||
|
position (0), size (0), availableSize (destBufferSize)
|
||||||
|
{
|
||||||
|
bassert (externalData != nullptr); // This must be a valid pointer.
|
||||||
|
}
|
||||||
|
|
||||||
MemoryOutputStream::~MemoryOutputStream()
|
MemoryOutputStream::~MemoryOutputStream()
|
||||||
{
|
{
|
||||||
trimExternalBlockSize();
|
trimExternalBlockSize();
|
||||||
@@ -51,13 +56,14 @@ void MemoryOutputStream::flush()
|
|||||||
|
|
||||||
void MemoryOutputStream::trimExternalBlockSize()
|
void MemoryOutputStream::trimExternalBlockSize()
|
||||||
{
|
{
|
||||||
if (&data != &internalBlock)
|
if (blockToUse != &internalBlock && blockToUse != nullptr)
|
||||||
data.setSize (size, false);
|
blockToUse->setSize (size, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MemoryOutputStream::preallocate (const size_t bytesToPreallocate)
|
void MemoryOutputStream::preallocate (const size_t bytesToPreallocate)
|
||||||
{
|
{
|
||||||
data.ensureSize (bytesToPreallocate + 1);
|
if (blockToUse != nullptr)
|
||||||
|
blockToUse->ensureSize (bytesToPreallocate + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MemoryOutputStream::reset() noexcept
|
void MemoryOutputStream::reset() noexcept
|
||||||
@@ -71,10 +77,24 @@ char* MemoryOutputStream::prepareToWrite (size_t numBytes)
|
|||||||
bassert ((ssize_t) numBytes >= 0);
|
bassert ((ssize_t) numBytes >= 0);
|
||||||
size_t storageNeeded = position + numBytes;
|
size_t storageNeeded = position + numBytes;
|
||||||
|
|
||||||
if (storageNeeded >= data.getSize())
|
char* data;
|
||||||
data.ensureSize ((storageNeeded + bmin (storageNeeded / 2, (size_t) (1024 * 1024)) + 32) & ~31u);
|
|
||||||
|
|
||||||
char* const writePointer = static_cast <char*> (data.getData()) + position;
|
if (blockToUse != nullptr)
|
||||||
|
{
|
||||||
|
if (storageNeeded >= blockToUse->getSize())
|
||||||
|
blockToUse->ensureSize ((storageNeeded + bmin (storageNeeded / 2, (size_t) (1024 * 1024)) + 32) & ~31u);
|
||||||
|
|
||||||
|
data = static_cast <char*> (blockToUse->getData());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (storageNeeded > availableSize)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
data = static_cast <char*> (externalData);
|
||||||
|
}
|
||||||
|
|
||||||
|
char* const writePointer = data + position;
|
||||||
position += numBytes;
|
position += numBytes;
|
||||||
size = bmax (size, position);
|
size = bmax (size, position);
|
||||||
return writePointer;
|
return writePointer;
|
||||||
@@ -82,25 +102,43 @@ char* MemoryOutputStream::prepareToWrite (size_t numBytes)
|
|||||||
|
|
||||||
bool MemoryOutputStream::write (const void* const buffer, size_t howMany)
|
bool MemoryOutputStream::write (const void* const buffer, size_t howMany)
|
||||||
{
|
{
|
||||||
bassert (buffer != nullptr && ((ssize_t) howMany) >= 0);
|
bassert (buffer != nullptr);
|
||||||
|
|
||||||
if (howMany > 0)
|
|
||||||
memcpy (prepareToWrite (howMany), buffer, howMany);
|
|
||||||
|
|
||||||
|
if (howMany == 0)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
if (char* dest = prepareToWrite (howMany))
|
||||||
|
{
|
||||||
|
memcpy (dest, buffer, howMany);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MemoryOutputStream::writeRepeatedByte (uint8 byte, size_t howMany)
|
bool MemoryOutputStream::writeRepeatedByte (uint8 byte, size_t howMany)
|
||||||
{
|
{
|
||||||
if (howMany > 0)
|
if (howMany == 0)
|
||||||
memset (prepareToWrite (howMany), byte, howMany);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
if (char* dest = prepareToWrite (howMany))
|
||||||
|
{
|
||||||
|
memset (dest, byte, howMany);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MemoryOutputStream::appendUTF8Char (beast_wchar c)
|
bool MemoryOutputStream::appendUTF8Char (beast_wchar c)
|
||||||
{
|
{
|
||||||
CharPointer_UTF8 (prepareToWrite (CharPointer_UTF8::getBytesRequiredFor (c))).write (c);
|
if (char* dest = prepareToWrite (CharPointer_UTF8::getBytesRequiredFor (c)))
|
||||||
|
{
|
||||||
|
CharPointer_UTF8 (dest).write (c);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
MemoryBlock MemoryOutputStream::getMemoryBlock() const
|
MemoryBlock MemoryOutputStream::getMemoryBlock() const
|
||||||
@@ -110,10 +148,13 @@ MemoryBlock MemoryOutputStream::getMemoryBlock() const
|
|||||||
|
|
||||||
const void* MemoryOutputStream::getData() const noexcept
|
const void* MemoryOutputStream::getData() const noexcept
|
||||||
{
|
{
|
||||||
if (data.getSize() > size)
|
if (blockToUse == nullptr)
|
||||||
static_cast <char*> (data.getData()) [size] = 0;
|
return externalData;
|
||||||
|
|
||||||
return data.getData();
|
if (blockToUse->getSize() > size)
|
||||||
|
static_cast <char*> (blockToUse->getData()) [size] = 0;
|
||||||
|
|
||||||
|
return blockToUse->getData();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MemoryOutputStream::setPosition (int64 newPosition)
|
bool MemoryOutputStream::setPosition (int64 newPosition)
|
||||||
@@ -139,7 +180,8 @@ int MemoryOutputStream::writeFromInputStream (InputStream& source, int64 maxNumB
|
|||||||
if (maxNumBytesToWrite > availableData)
|
if (maxNumBytesToWrite > availableData)
|
||||||
maxNumBytesToWrite = availableData;
|
maxNumBytesToWrite = availableData;
|
||||||
|
|
||||||
preallocate (data.getSize() + (size_t) maxNumBytesToWrite);
|
if (blockToUse != nullptr)
|
||||||
|
preallocate (blockToUse->getSize() + (size_t) maxNumBytesToWrite);
|
||||||
}
|
}
|
||||||
|
|
||||||
return OutputStream::writeFromInputStream (source, maxNumBytesToWrite);
|
return OutputStream::writeFromInputStream (source, maxNumBytesToWrite);
|
||||||
|
|||||||
@@ -28,6 +28,13 @@
|
|||||||
#include "../memory/beast_MemoryBlock.h"
|
#include "../memory/beast_MemoryBlock.h"
|
||||||
#include "../memory/beast_ScopedPointer.h"
|
#include "../memory/beast_ScopedPointer.h"
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
/**
|
||||||
|
Writes data to an internal memory buffer, which grows as required.
|
||||||
|
|
||||||
|
The data that was written into the stream can then be accessed later as
|
||||||
|
a contiguous block of memory.
|
||||||
|
*/
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
/**
|
/**
|
||||||
Writes data to an internal memory buffer, which grows as required.
|
Writes data to an internal memory buffer, which grows as required.
|
||||||
@@ -42,7 +49,6 @@ class BEAST_API MemoryOutputStream
|
|||||||
public:
|
public:
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
/** Creates an empty memory stream, ready to be written into.
|
/** Creates an empty memory stream, ready to be written into.
|
||||||
|
|
||||||
@param initialSize the intial amount of capacity to allocate for writing into
|
@param initialSize the intial amount of capacity to allocate for writing into
|
||||||
*/
|
*/
|
||||||
MemoryOutputStream (size_t initialSize = 256);
|
MemoryOutputStream (size_t initialSize = 256);
|
||||||
@@ -62,6 +68,14 @@ public:
|
|||||||
MemoryOutputStream (MemoryBlock& memoryBlockToWriteTo,
|
MemoryOutputStream (MemoryBlock& memoryBlockToWriteTo,
|
||||||
bool appendToExistingBlockContent);
|
bool appendToExistingBlockContent);
|
||||||
|
|
||||||
|
/** Creates a MemoryOutputStream that will write into a user-supplied, fixed-size
|
||||||
|
block of memory.
|
||||||
|
|
||||||
|
When using this mode, the stream will write directly into this memory area until
|
||||||
|
it's full, at which point write operations will fail.
|
||||||
|
*/
|
||||||
|
MemoryOutputStream (void* destBuffer, size_t destBufferSize);
|
||||||
|
|
||||||
/** Destructor.
|
/** Destructor.
|
||||||
This will free any data that was written to it.
|
This will free any data that was written to it.
|
||||||
*/
|
*/
|
||||||
@@ -87,7 +101,7 @@ public:
|
|||||||
void preallocate (size_t bytesToPreallocate);
|
void preallocate (size_t bytesToPreallocate);
|
||||||
|
|
||||||
/** Appends the utf-8 bytes for a unicode character */
|
/** Appends the utf-8 bytes for a unicode character */
|
||||||
void appendUTF8Char (beast_wchar character);
|
bool appendUTF8Char (beast_wchar character);
|
||||||
|
|
||||||
/** Returns a String created from the (UTF8) data that has been written to the stream. */
|
/** Returns a String created from the (UTF8) data that has been written to the stream. */
|
||||||
String toUTF8() const;
|
String toUTF8() const;
|
||||||
@@ -114,17 +128,17 @@ public:
|
|||||||
bool writeRepeatedByte (uint8 byte, size_t numTimesToRepeat) override;
|
bool writeRepeatedByte (uint8 byte, size_t numTimesToRepeat) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
//==============================================================================
|
|
||||||
MemoryBlock& data;
|
|
||||||
MemoryBlock internalBlock;
|
|
||||||
size_t position, size;
|
|
||||||
|
|
||||||
void trimExternalBlockSize();
|
void trimExternalBlockSize();
|
||||||
char* prepareToWrite (size_t);
|
char* prepareToWrite (size_t);
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
MemoryBlock* const blockToUse;
|
||||||
|
MemoryBlock internalBlock;
|
||||||
|
void* externalData;
|
||||||
|
size_t position, size, availableSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Copies all the data that has been written to a MemoryOutputStream into another stream. */
|
/** Copies all the data that has been written to a MemoryOutputStream into another stream. */
|
||||||
OutputStream& BEAST_CALLTYPE operator<< (OutputStream& stream, const MemoryOutputStream& streamToRead);
|
OutputStream& BEAST_CALLTYPE operator<< (OutputStream& stream, const MemoryOutputStream& streamToRead);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
Reference in New Issue
Block a user