@@ -0,0 +1,167 @@ | |||||
/* | |||||
============================================================================== | |||||
This file is part of the Water library. | |||||
Copyright (c) 2016 - ROLI Ltd. | |||||
Copyright (C) 2021 Filipe Coelho <falktx@falktx.com> | |||||
Permission is granted to use this software under the terms of the ISC license | |||||
http://www.isc.org/downloads/software-support-policy/isc-license/ | |||||
Permission to use, copy, modify, and/or distribute this software for any | |||||
purpose with or without fee is hereby granted, provided that the above | |||||
copyright notice and this permission notice appear in all copies. | |||||
THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD | |||||
TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND | |||||
FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, | |||||
OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF | |||||
USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER | |||||
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE | |||||
OF THIS SOFTWARE. | |||||
============================================================================== | |||||
*/ | |||||
#include "MemoryInputStream.h" | |||||
namespace water { | |||||
MemoryInputStream::MemoryInputStream (const void* const sourceData, | |||||
const size_t sourceDataSize, | |||||
const bool keepInternalCopy) | |||||
: data (sourceData), | |||||
dataSize (sourceDataSize), | |||||
position (0) | |||||
{ | |||||
if (keepInternalCopy) | |||||
createInternalCopy(); | |||||
} | |||||
MemoryInputStream::MemoryInputStream (const MemoryBlock& sourceData, | |||||
const bool keepInternalCopy) | |||||
: data (sourceData.getData()), | |||||
dataSize (sourceData.getSize()), | |||||
position (0) | |||||
{ | |||||
if (keepInternalCopy) | |||||
createInternalCopy(); | |||||
} | |||||
void MemoryInputStream::createInternalCopy() | |||||
{ | |||||
internalCopy.malloc (dataSize); | |||||
memcpy (internalCopy, data, dataSize); | |||||
data = internalCopy; | |||||
} | |||||
MemoryInputStream::~MemoryInputStream() | |||||
{ | |||||
} | |||||
int64 MemoryInputStream::getTotalLength() | |||||
{ | |||||
return (int64) dataSize; | |||||
} | |||||
int MemoryInputStream::read (void* const buffer, const int howMany) | |||||
{ | |||||
wassert (buffer != nullptr && howMany >= 0); | |||||
if (howMany <= 0 || position >= dataSize) | |||||
return 0; | |||||
const size_t num = jmin ((size_t) howMany, dataSize - position); | |||||
if (num > 0) | |||||
{ | |||||
memcpy (buffer, addBytesToPointer (data, position), num); | |||||
position += num; | |||||
} | |||||
return (int) num; | |||||
} | |||||
bool MemoryInputStream::isExhausted() | |||||
{ | |||||
return position >= dataSize; | |||||
} | |||||
bool MemoryInputStream::setPosition (const int64 pos) | |||||
{ | |||||
position = (size_t) jlimit ((int64) 0, (int64) dataSize, pos); | |||||
return true; | |||||
} | |||||
int64 MemoryInputStream::getPosition() | |||||
{ | |||||
return (int64) position; | |||||
} | |||||
//============================================================================== | |||||
#if WATER_UNIT_TESTS | |||||
class MemoryStreamTests : public UnitTest | |||||
{ | |||||
public: | |||||
MemoryStreamTests() : UnitTest ("MemoryInputStream & MemoryOutputStream") {} | |||||
void runTest() override | |||||
{ | |||||
beginTest ("Basics"); | |||||
Random r = getRandom(); | |||||
int randomInt = r.nextInt(); | |||||
int64 randomInt64 = r.nextInt64(); | |||||
double randomDouble = r.nextDouble(); | |||||
String randomString (createRandomWideCharString (r)); | |||||
MemoryOutputStream mo; | |||||
mo.writeInt (randomInt); | |||||
mo.writeIntBigEndian (randomInt); | |||||
mo.writeCompressedInt (randomInt); | |||||
mo.writeString (randomString); | |||||
mo.writeInt64 (randomInt64); | |||||
mo.writeInt64BigEndian (randomInt64); | |||||
mo.writeDouble (randomDouble); | |||||
mo.writeDoubleBigEndian (randomDouble); | |||||
MemoryInputStream mi (mo.getData(), mo.getDataSize(), false); | |||||
expect (mi.readInt() == randomInt); | |||||
expect (mi.readIntBigEndian() == randomInt); | |||||
expect (mi.readCompressedInt() == randomInt); | |||||
expectEquals (mi.readString(), randomString); | |||||
expect (mi.readInt64() == randomInt64); | |||||
expect (mi.readInt64BigEndian() == randomInt64); | |||||
expect (mi.readDouble() == randomDouble); | |||||
expect (mi.readDoubleBigEndian() == randomDouble); | |||||
} | |||||
static String createRandomWideCharString (Random& r) | |||||
{ | |||||
water_wchar buffer [50] = { 0 }; | |||||
for (int i = 0; i < numElementsInArray (buffer) - 1; ++i) | |||||
{ | |||||
if (r.nextBool()) | |||||
{ | |||||
do | |||||
{ | |||||
buffer[i] = (water_wchar) (1 + r.nextInt (0x10ffff - 1)); | |||||
} | |||||
while (! CharPointer_UTF16::canRepresent (buffer[i])); | |||||
} | |||||
else | |||||
buffer[i] = (water_wchar) (1 + r.nextInt (0xff)); | |||||
} | |||||
return CharPointer_UTF32 (buffer); | |||||
} | |||||
}; | |||||
static MemoryStreamTests memoryInputStreamUnitTests; | |||||
#endif | |||||
} |
@@ -0,0 +1,101 @@ | |||||
/* | |||||
============================================================================== | |||||
This file is part of the Water library. | |||||
Copyright (c) 2016 - ROLI Ltd. | |||||
Copyright (C) 2021 Filipe Coelho <falktx@falktx.com> | |||||
Permission is granted to use this software under the terms of the ISC license | |||||
http://www.isc.org/downloads/software-support-policy/isc-license/ | |||||
Permission to use, copy, modify, and/or distribute this software for any | |||||
purpose with or without fee is hereby granted, provided that the above | |||||
copyright notice and this permission notice appear in all copies. | |||||
THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD | |||||
TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND | |||||
FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, | |||||
OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF | |||||
USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER | |||||
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE | |||||
OF THIS SOFTWARE. | |||||
============================================================================== | |||||
*/ | |||||
#ifndef WATER_MEMORYINPUTSTREAM_H_INCLUDED | |||||
#define WATER_MEMORYINPUTSTREAM_H_INCLUDED | |||||
#include "InputStream.h" | |||||
#include "../memory/MemoryBlock.h" | |||||
#include "../memory/HeapBlock.h" | |||||
namespace water { | |||||
//============================================================================== | |||||
/** | |||||
Allows a block of data to be accessed as a stream. | |||||
This can either be used to refer to a shared block of memory, or can make its | |||||
own internal copy of the data when the MemoryInputStream is created. | |||||
*/ | |||||
class MemoryInputStream : public InputStream | |||||
{ | |||||
public: | |||||
//============================================================================== | |||||
/** Creates a MemoryInputStream. | |||||
@param sourceData the block of data to use as the stream's source | |||||
@param sourceDataSize the number of bytes in the source data block | |||||
@param keepInternalCopyOfData if false, the stream will just keep a pointer to | |||||
the source data, so this data shouldn't be changed | |||||
for the lifetime of the stream; if this parameter is | |||||
true, the stream will make its own copy of the | |||||
data and use that. | |||||
*/ | |||||
MemoryInputStream (const void* sourceData, | |||||
size_t sourceDataSize, | |||||
bool keepInternalCopyOfData); | |||||
/** Creates a MemoryInputStream. | |||||
@param data a block of data to use as the stream's source | |||||
@param keepInternalCopyOfData if false, the stream will just keep a reference to | |||||
the source data, so this data shouldn't be changed | |||||
for the lifetime of the stream; if this parameter is | |||||
true, the stream will make its own copy of the | |||||
data and use that. | |||||
*/ | |||||
MemoryInputStream (const MemoryBlock& data, | |||||
bool keepInternalCopyOfData); | |||||
/** Destructor. */ | |||||
~MemoryInputStream(); | |||||
/** Returns a pointer to the source data block from which this stream is reading. */ | |||||
const void* getData() const noexcept { return data; } | |||||
/** Returns the number of bytes of source data in the block from which this stream is reading. */ | |||||
size_t getDataSize() const noexcept { return dataSize; } | |||||
//============================================================================== | |||||
int64 getPosition() override; | |||||
bool setPosition (int64 pos) override; | |||||
int64 getTotalLength() override; | |||||
bool isExhausted() override; | |||||
int read (void* destBuffer, int maxBytesToRead) override; | |||||
private: | |||||
//============================================================================== | |||||
const void* data; | |||||
size_t dataSize, position; | |||||
HeapBlock<char> internalCopy; | |||||
void createInternalCopy(); | |||||
CARLA_DECLARE_NON_COPY_CLASS (MemoryInputStream) | |||||
}; | |||||
} | |||||
#endif // WATER_MEMORYINPUTSTREAM_H_INCLUDED |
@@ -69,6 +69,7 @@ BOOL WINAPI DllMain(HINSTANCE hInst, DWORD, LPVOID) | |||||
#include "streams/FileInputSource.cpp" | #include "streams/FileInputSource.cpp" | ||||
#include "streams/InputStream.cpp" | #include "streams/InputStream.cpp" | ||||
#include "streams/MemoryInputStream.cpp" | |||||
#include "streams/MemoryOutputStream.cpp" | #include "streams/MemoryOutputStream.cpp" | ||||
#include "streams/OutputStream.cpp" | #include "streams/OutputStream.cpp" | ||||
@@ -51,6 +51,7 @@ HINSTANCE getCurrentModuleInstanceHandle() noexcept | |||||
# include "maths/Random.cpp" | # include "maths/Random.cpp" | ||||
# include "memory/MemoryBlock.cpp" | # include "memory/MemoryBlock.cpp" | ||||
# include "streams/InputStream.cpp" | # include "streams/InputStream.cpp" | ||||
# include "streams/MemoryInputStream.cpp" | |||||
# include "streams/MemoryOutputStream.cpp" | # include "streams/MemoryOutputStream.cpp" | ||||
# include "streams/OutputStream.cpp" | # include "streams/OutputStream.cpp" | ||||
#endif | #endif |