@@ -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/InputStream.cpp" | |||
#include "streams/MemoryInputStream.cpp" | |||
#include "streams/MemoryOutputStream.cpp" | |||
#include "streams/OutputStream.cpp" | |||
@@ -51,6 +51,7 @@ HINSTANCE getCurrentModuleInstanceHandle() noexcept | |||
# include "maths/Random.cpp" | |||
# include "memory/MemoryBlock.cpp" | |||
# include "streams/InputStream.cpp" | |||
# include "streams/MemoryInputStream.cpp" | |||
# include "streams/MemoryOutputStream.cpp" | |||
# include "streams/OutputStream.cpp" | |||
#endif |