Browse Source

Added a MemoryOutputStream constructor to write into a fixed block of memory.

tags/2021-05-28
jules 12 years ago
parent
commit
9f97ff341b
3 changed files with 81 additions and 61 deletions
  1. +3
    -32
      modules/juce_core/streams/juce_InputStream.h
  2. +67
    -25
      modules/juce_core/streams/juce_MemoryOutputStream.cpp
  3. +11
    -4
      modules/juce_core/streams/juce_MemoryOutputStream.h

+ 3
- 32
modules/juce_core/streams/juce_InputStream.h View File

@@ -86,41 +86,28 @@ public:
virtual int read (void* destBuffer, int maxBytesToRead) = 0; virtual int read (void* destBuffer, int maxBytesToRead) = 0;
/** Reads a byte from the stream. /** Reads a byte from the stream.
If the stream is exhausted, this will return zero. If the stream is exhausted, this will return zero.
@see OutputStream::writeByte @see OutputStream::writeByte
*/ */
virtual char readByte(); virtual char readByte();
/** Reads a boolean from the stream. /** 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. If the stream is exhausted, this will return false.
@see OutputStream::writeBool @see OutputStream::writeBool
*/ */
virtual bool readBool(); virtual bool readBool();
/** 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
(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. If the stream is exhausted partway through reading the bytes, this will return zero.
@see OutputStream::writeShort, readShortBigEndian @see OutputStream::writeShort, readShortBigEndian
*/ */
virtual short readShort(); virtual short readShort();
/** 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
(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. If the stream is exhausted partway through reading the bytes, this will return zero.
@see OutputStream::writeShortBigEndian, readShort @see OutputStream::writeShortBigEndian, readShort
*/ */
virtual short readShortBigEndian(); virtual short readShortBigEndian();
@@ -170,51 +157,36 @@ public:
virtual int64 readInt64BigEndian(); virtual int64 readInt64BigEndian();
/** Reads four bytes as a 32-bit floating point value. /** 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. 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. If the stream is exhausted partway through reading the bytes, this will return zero.
@see OutputStream::writeFloat, readDouble @see OutputStream::writeFloat, readDouble
*/ */
virtual float readFloat(); virtual float readFloat();
/** Reads four bytes as a 32-bit floating point value. /** 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. 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. If the stream is exhausted partway through reading the bytes, this will return zero.
@see OutputStream::writeFloatBigEndian, readDoubleBigEndian @see OutputStream::writeFloatBigEndian, readDoubleBigEndian
*/ */
virtual float readFloatBigEndian(); virtual float readFloatBigEndian();
/** Reads eight bytes as a 64-bit floating point value. /** 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. 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. If the stream is exhausted partway through reading the bytes, this will return zero.
@see OutputStream::writeDouble, readFloat @see OutputStream::writeDouble, readFloat
*/ */
virtual double readDouble(); virtual double readDouble();
/** Reads eight bytes as a 64-bit floating point value. /** 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. 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. If the stream is exhausted partway through reading the bytes, this will return zero.
@see OutputStream::writeDoubleBigEndian, readFloatBigEndian @see OutputStream::writeDoubleBigEndian, readFloatBigEndian
*/ */
virtual double readDoubleBigEndian(); virtual double readDoubleBigEndian();
/** Reads an encoded 32-bit number from the stream using a space-saving compressed format. /** 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() 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. The format used is: number of significant bytes + up to 4 bytes in little-endian order.
@see OutputStream::writeCompressedInt() @see OutputStream::writeCompressedInt()
*/ */
virtual int readCompressedInt(); virtual int readCompressedInt();
@@ -259,7 +231,6 @@ public:
//============================================================================== //==============================================================================
/** Returns the offset of the next byte that will be read from the stream. /** Returns the offset of the next byte that will be read from the stream.
@see setPosition @see setPosition
*/ */
virtual int64 getPosition() = 0; virtual int64 getPosition() = 0;


+ 67
- 25
modules/juce_core/streams/juce_MemoryOutputStream.cpp View File

@@ -27,23 +27,28 @@
*/ */
MemoryOutputStream::MemoryOutputStream (const size_t initialSize) 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); internalBlock.setSize (initialSize, false);
} }
MemoryOutputStream::MemoryOutputStream (MemoryBlock& memoryBlockToWriteTo, MemoryOutputStream::MemoryOutputStream (MemoryBlock& memoryBlockToWriteTo,
const bool appendToExistingBlockContent) const bool appendToExistingBlockContent)
: data (memoryBlockToWriteTo),
position (0),
size (0)
: blockToUse (&memoryBlockToWriteTo), externalData (nullptr),
position (0), size (0), availableSize (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)
{
jassert (externalData != nullptr); // This must be a valid pointer.
}
MemoryOutputStream::~MemoryOutputStream() MemoryOutputStream::~MemoryOutputStream()
{ {
trimExternalBlockSize(); trimExternalBlockSize();
@@ -56,13 +61,14 @@ void MemoryOutputStream::flush()
void MemoryOutputStream::trimExternalBlockSize() 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) 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
@@ -76,10 +82,24 @@ char* MemoryOutputStream::prepareToWrite (size_t numBytes)
jassert ((ssize_t) numBytes >= 0); jassert ((ssize_t) numBytes >= 0);
size_t storageNeeded = position + numBytes; size_t storageNeeded = position + numBytes;
if (storageNeeded >= data.getSize())
data.ensureSize ((storageNeeded + jmin (storageNeeded / 2, (size_t) (1024 * 1024)) + 32) & ~31u);
char* data;
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 = static_cast <char*> (data.getData()) + position;
char* const writePointer = data + position;
position += numBytes; position += numBytes;
size = jmax (size, position); size = jmax (size, position);
return writePointer; return writePointer;
@@ -87,25 +107,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)
{ {
jassert (buffer != nullptr && ((ssize_t) howMany) >= 0);
jassert (buffer != nullptr);
if (howMany > 0)
memcpy (prepareToWrite (howMany), buffer, howMany);
if (howMany == 0)
return true;
if (char* dest = prepareToWrite (howMany))
{
memcpy (dest, buffer, howMany);
return true;
}
return true;
return false;
} }
bool MemoryOutputStream::writeRepeatedByte (uint8 byte, size_t howMany) bool MemoryOutputStream::writeRepeatedByte (uint8 byte, size_t howMany)
{ {
if (howMany > 0)
memset (prepareToWrite (howMany), byte, howMany);
if (howMany == 0)
return true;
if (char* dest = prepareToWrite (howMany))
{
memset (dest, byte, howMany);
return true;
}
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 MemoryBlock MemoryOutputStream::getMemoryBlock() const
@@ -115,10 +153,13 @@ MemoryBlock MemoryOutputStream::getMemoryBlock() const
const void* MemoryOutputStream::getData() const noexcept const void* MemoryOutputStream::getData() const noexcept
{ {
if (data.getSize() > size)
static_cast <char*> (data.getData()) [size] = 0;
if (blockToUse == nullptr)
return externalData;
if (blockToUse->getSize() > size)
static_cast <char*> (blockToUse->getData()) [size] = 0;
return data.getData();
return blockToUse->getData();
} }
bool MemoryOutputStream::setPosition (int64 newPosition) bool MemoryOutputStream::setPosition (int64 newPosition)
@@ -144,7 +185,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);


+ 11
- 4
modules/juce_core/streams/juce_MemoryOutputStream.h View File

@@ -46,7 +46,6 @@ class JUCE_API MemoryOutputStream : public OutputStream
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);
@@ -66,6 +65,13 @@ 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.
*/ */
@@ -91,7 +97,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 (juce_wchar character);
bool appendUTF8Char (juce_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;
@@ -119,9 +125,10 @@ public:
private: private:
//============================================================================== //==============================================================================
MemoryBlock& data;
MemoryBlock* const blockToUse;
MemoryBlock internalBlock; MemoryBlock internalBlock;
size_t position, size;
void* externalData;
size_t position, size, availableSize;
void trimExternalBlockSize(); void trimExternalBlockSize();
char* prepareToWrite (size_t); char* prepareToWrite (size_t);


Loading…
Cancel
Save