mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
Added a MemoryOutputStream constructor to write into a fixed block of memory.
This commit is contained in:
parent
e661096762
commit
9f97ff341b
3 changed files with 81 additions and 61 deletions
|
|
@ -86,41 +86,28 @@ public:
|
|||
virtual int read (void* destBuffer, int maxBytesToRead) = 0;
|
||||
|
||||
/** Reads a byte from the stream.
|
||||
|
||||
If the stream is exhausted, this will return zero.
|
||||
|
||||
@see OutputStream::writeByte
|
||||
*/
|
||||
virtual char readByte();
|
||||
|
||||
/** Reads a boolean from the stream.
|
||||
|
||||
The bool is encoded as a single byte - 1 for true, 0 for false.
|
||||
|
||||
The bool is encoded as a single byte - non-zero for true, 0 for false.
|
||||
If the stream is exhausted, this will return false.
|
||||
|
||||
@see OutputStream::writeBool
|
||||
*/
|
||||
virtual bool readBool();
|
||||
|
||||
/** 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
|
||||
(byte1 | (byte2 << 8)).
|
||||
|
||||
If the next two bytes read are byte1 and byte2, this returns (byte1 | (byte2 << 8)).
|
||||
If the stream is exhausted partway through reading the bytes, this will return zero.
|
||||
|
||||
@see OutputStream::writeShort, readShortBigEndian
|
||||
*/
|
||||
virtual short readShort();
|
||||
|
||||
/** 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
|
||||
(byte2 | (byte1 << 8)).
|
||||
|
||||
If the next two bytes read are byte1 and byte2, this returns (byte2 | (byte1 << 8)).
|
||||
If the stream is exhausted partway through reading the bytes, this will return zero.
|
||||
|
||||
@see OutputStream::writeShortBigEndian, readShort
|
||||
*/
|
||||
virtual short readShortBigEndian();
|
||||
|
|
@ -170,51 +157,36 @@ public:
|
|||
virtual int64 readInt64BigEndian();
|
||||
|
||||
/** Reads four bytes as a 32-bit floating point value.
|
||||
|
||||
The raw 32-bit encoding of the float is read from the stream as a little-endian int.
|
||||
|
||||
If the stream is exhausted partway through reading the bytes, this will return zero.
|
||||
|
||||
@see OutputStream::writeFloat, readDouble
|
||||
*/
|
||||
virtual float readFloat();
|
||||
|
||||
/** Reads four bytes as a 32-bit floating point value.
|
||||
|
||||
The raw 32-bit encoding of the float is read from the stream as a big-endian int.
|
||||
|
||||
If the stream is exhausted partway through reading the bytes, this will return zero.
|
||||
|
||||
@see OutputStream::writeFloatBigEndian, readDoubleBigEndian
|
||||
*/
|
||||
virtual float readFloatBigEndian();
|
||||
|
||||
/** Reads eight bytes as a 64-bit floating point value.
|
||||
|
||||
The raw 64-bit encoding of the double is read from the stream as a little-endian int64.
|
||||
|
||||
If the stream is exhausted partway through reading the bytes, this will return zero.
|
||||
|
||||
@see OutputStream::writeDouble, readFloat
|
||||
*/
|
||||
virtual double readDouble();
|
||||
|
||||
/** Reads eight bytes as a 64-bit floating point value.
|
||||
|
||||
The raw 64-bit encoding of the double is read from the stream as a big-endian int64.
|
||||
|
||||
If the stream is exhausted partway through reading the bytes, this will return zero.
|
||||
|
||||
@see OutputStream::writeDoubleBigEndian, readFloatBigEndian
|
||||
*/
|
||||
virtual double readDoubleBigEndian();
|
||||
|
||||
/** Reads an encoded 32-bit number from the stream using a space-saving compressed format.
|
||||
|
||||
For small values, this is more space-efficient than using readInt() and OutputStream::writeInt()
|
||||
|
||||
The format used is: number of significant bytes + up to 4 bytes in little-endian order.
|
||||
|
||||
@see OutputStream::writeCompressedInt()
|
||||
*/
|
||||
virtual int readCompressedInt();
|
||||
|
|
@ -259,7 +231,6 @@ public:
|
|||
|
||||
//==============================================================================
|
||||
/** Returns the offset of the next byte that will be read from the stream.
|
||||
|
||||
@see setPosition
|
||||
*/
|
||||
virtual int64 getPosition() = 0;
|
||||
|
|
|
|||
|
|
@ -27,23 +27,28 @@
|
|||
*/
|
||||
|
||||
MemoryOutputStream::MemoryOutputStream (const size_t initialSize)
|
||||
: data (internalBlock),
|
||||
position (0),
|
||||
size (0)
|
||||
: blockToUse (&internalBlock), externalData (nullptr),
|
||||
position (0), size (0), availableSize (0)
|
||||
{
|
||||
internalBlock.setSize (initialSize, false);
|
||||
}
|
||||
|
||||
MemoryOutputStream::MemoryOutputStream (MemoryBlock& memoryBlockToWriteTo,
|
||||
const bool appendToExistingBlockContent)
|
||||
: data (memoryBlockToWriteTo),
|
||||
position (0),
|
||||
size (0)
|
||||
: blockToUse (&memoryBlockToWriteTo), externalData (nullptr),
|
||||
position (0), size (0), availableSize (0)
|
||||
{
|
||||
if (appendToExistingBlockContent)
|
||||
position = size = memoryBlockToWriteTo.getSize();
|
||||
}
|
||||
|
||||
MemoryOutputStream::MemoryOutputStream (void* destBuffer, size_t destBufferSize)
|
||||
: blockToUse (nullptr), externalData (destBuffer),
|
||||
position (0), size (0), availableSize (destBufferSize)
|
||||
{
|
||||
jassert (externalData != nullptr); // This must be a valid pointer.
|
||||
}
|
||||
|
||||
MemoryOutputStream::~MemoryOutputStream()
|
||||
{
|
||||
trimExternalBlockSize();
|
||||
|
|
@ -56,13 +61,14 @@ void MemoryOutputStream::flush()
|
|||
|
||||
void MemoryOutputStream::trimExternalBlockSize()
|
||||
{
|
||||
if (&data != &internalBlock)
|
||||
data.setSize (size, false);
|
||||
if (blockToUse != &internalBlock && blockToUse != nullptr)
|
||||
blockToUse->setSize (size, false);
|
||||
}
|
||||
|
||||
void MemoryOutputStream::preallocate (const size_t bytesToPreallocate)
|
||||
{
|
||||
data.ensureSize (bytesToPreallocate + 1);
|
||||
if (blockToUse != nullptr)
|
||||
blockToUse->ensureSize (bytesToPreallocate + 1);
|
||||
}
|
||||
|
||||
void MemoryOutputStream::reset() noexcept
|
||||
|
|
@ -76,10 +82,24 @@ char* MemoryOutputStream::prepareToWrite (size_t numBytes)
|
|||
jassert ((ssize_t) numBytes >= 0);
|
||||
size_t storageNeeded = position + numBytes;
|
||||
|
||||
if (storageNeeded >= data.getSize())
|
||||
data.ensureSize ((storageNeeded + jmin (storageNeeded / 2, (size_t) (1024 * 1024)) + 32) & ~31u);
|
||||
char* data;
|
||||
|
||||
char* const writePointer = static_cast <char*> (data.getData()) + position;
|
||||
if (blockToUse != nullptr)
|
||||
{
|
||||
if (storageNeeded >= blockToUse->getSize())
|
||||
blockToUse->ensureSize ((storageNeeded + jmin (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;
|
||||
size = jmax (size, position);
|
||||
return writePointer;
|
||||
|
|
@ -87,25 +107,43 @@ char* MemoryOutputStream::prepareToWrite (size_t numBytes)
|
|||
|
||||
bool MemoryOutputStream::write (const void* const buffer, size_t howMany)
|
||||
{
|
||||
jassert (buffer != nullptr && ((ssize_t) howMany) >= 0);
|
||||
jassert (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)
|
||||
{
|
||||
if (howMany > 0)
|
||||
memset (prepareToWrite (howMany), byte, howMany);
|
||||
if (howMany == 0)
|
||||
return true;
|
||||
|
||||
return true;
|
||||
if (char* dest = prepareToWrite (howMany))
|
||||
{
|
||||
memset (dest, byte, howMany);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void MemoryOutputStream::appendUTF8Char (juce_wchar c)
|
||||
bool MemoryOutputStream::appendUTF8Char (juce_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
|
||||
|
|
@ -115,10 +153,13 @@ MemoryBlock MemoryOutputStream::getMemoryBlock() const
|
|||
|
||||
const void* MemoryOutputStream::getData() const noexcept
|
||||
{
|
||||
if (data.getSize() > size)
|
||||
static_cast <char*> (data.getData()) [size] = 0;
|
||||
if (blockToUse == nullptr)
|
||||
return externalData;
|
||||
|
||||
return data.getData();
|
||||
if (blockToUse->getSize() > size)
|
||||
static_cast <char*> (blockToUse->getData()) [size] = 0;
|
||||
|
||||
return blockToUse->getData();
|
||||
}
|
||||
|
||||
bool MemoryOutputStream::setPosition (int64 newPosition)
|
||||
|
|
@ -144,7 +185,8 @@ int MemoryOutputStream::writeFromInputStream (InputStream& source, int64 maxNumB
|
|||
if (maxNumBytesToWrite > availableData)
|
||||
maxNumBytesToWrite = availableData;
|
||||
|
||||
preallocate (data.getSize() + (size_t) maxNumBytesToWrite);
|
||||
if (blockToUse != nullptr)
|
||||
preallocate (blockToUse->getSize() + (size_t) maxNumBytesToWrite);
|
||||
}
|
||||
|
||||
return OutputStream::writeFromInputStream (source, maxNumBytesToWrite);
|
||||
|
|
|
|||
|
|
@ -46,7 +46,6 @@ class JUCE_API MemoryOutputStream : public OutputStream
|
|||
public:
|
||||
//==============================================================================
|
||||
/** Creates an empty memory stream, ready to be written into.
|
||||
|
||||
@param initialSize the intial amount of capacity to allocate for writing into
|
||||
*/
|
||||
MemoryOutputStream (size_t initialSize = 256);
|
||||
|
|
@ -66,6 +65,13 @@ public:
|
|||
MemoryOutputStream (MemoryBlock& memoryBlockToWriteTo,
|
||||
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.
|
||||
This will free any data that was written to it.
|
||||
*/
|
||||
|
|
@ -91,7 +97,7 @@ public:
|
|||
void preallocate (size_t bytesToPreallocate);
|
||||
|
||||
/** Appends the utf-8 bytes for a unicode character */
|
||||
void appendUTF8Char (juce_wchar character);
|
||||
bool appendUTF8Char (juce_wchar character);
|
||||
|
||||
/** Returns a String created from the (UTF8) data that has been written to the stream. */
|
||||
String toUTF8() const;
|
||||
|
|
@ -119,9 +125,10 @@ public:
|
|||
|
||||
private:
|
||||
//==============================================================================
|
||||
MemoryBlock& data;
|
||||
MemoryBlock* const blockToUse;
|
||||
MemoryBlock internalBlock;
|
||||
size_t position, size;
|
||||
void* externalData;
|
||||
size_t position, size, availableSize;
|
||||
|
||||
void trimExternalBlockSize();
|
||||
char* prepareToWrite (size_t);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue