git subrepo clone --branch=sono6good https://github.com/essej/JUCE.git deps/juce
subrepo: subdir: "deps/juce" merged: "b13f9084e" upstream: origin: "https://github.com/essej/JUCE.git" branch: "sono6good" commit: "b13f9084e" git-subrepo: version: "0.4.3" origin: "https://github.com/ingydotnet/git-subrepo.git" commit: "2f68596"
This commit is contained in:
322
deps/juce/modules/juce_core/streams/juce_BufferedInputStream.cpp
vendored
Normal file
322
deps/juce/modules/juce_core/streams/juce_BufferedInputStream.cpp
vendored
Normal file
@ -0,0 +1,322 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
The code included in this file is provided 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.
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
static int calcBufferStreamBufferSize (int requestedSize, InputStream* source) noexcept
|
||||
{
|
||||
// You need to supply a real stream when creating a BufferedInputStream
|
||||
jassert (source != nullptr);
|
||||
|
||||
requestedSize = jmax (256, requestedSize);
|
||||
auto sourceSize = source->getTotalLength();
|
||||
|
||||
if (sourceSize >= 0 && sourceSize < requestedSize)
|
||||
return jmax (32, (int) sourceSize);
|
||||
|
||||
return requestedSize;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
BufferedInputStream::BufferedInputStream (InputStream* sourceStream, int size, bool takeOwnership)
|
||||
: source (sourceStream, takeOwnership),
|
||||
bufferedRange (sourceStream->getPosition(), sourceStream->getPosition()),
|
||||
position (bufferedRange.getStart()),
|
||||
bufferLength (calcBufferStreamBufferSize (size, sourceStream))
|
||||
{
|
||||
buffer.malloc (bufferLength);
|
||||
}
|
||||
|
||||
BufferedInputStream::BufferedInputStream (InputStream& sourceStream, int size)
|
||||
: BufferedInputStream (&sourceStream, size, false)
|
||||
{
|
||||
}
|
||||
|
||||
BufferedInputStream::~BufferedInputStream() = default;
|
||||
|
||||
//==============================================================================
|
||||
char BufferedInputStream::peekByte()
|
||||
{
|
||||
if (! ensureBuffered())
|
||||
return 0;
|
||||
|
||||
return position < lastReadPos ? buffer[(int) (position - bufferedRange.getStart())] : 0;
|
||||
}
|
||||
|
||||
int64 BufferedInputStream::getTotalLength()
|
||||
{
|
||||
return source->getTotalLength();
|
||||
}
|
||||
|
||||
int64 BufferedInputStream::getPosition()
|
||||
{
|
||||
return position;
|
||||
}
|
||||
|
||||
bool BufferedInputStream::setPosition (int64 newPosition)
|
||||
{
|
||||
position = jmax ((int64) 0, newPosition);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BufferedInputStream::isExhausted()
|
||||
{
|
||||
return position >= lastReadPos && source->isExhausted();
|
||||
}
|
||||
|
||||
bool BufferedInputStream::ensureBuffered()
|
||||
{
|
||||
auto bufferEndOverlap = lastReadPos - bufferOverlap;
|
||||
|
||||
if (position < bufferedRange.getStart() || position >= bufferEndOverlap)
|
||||
{
|
||||
int bytesRead = 0;
|
||||
|
||||
if (position < lastReadPos
|
||||
&& position >= bufferEndOverlap
|
||||
&& position >= bufferedRange.getStart())
|
||||
{
|
||||
auto bytesToKeep = (int) (lastReadPos - position);
|
||||
memmove (buffer, buffer + (int) (position - bufferedRange.getStart()), (size_t) bytesToKeep);
|
||||
|
||||
bytesRead = source->read (buffer + bytesToKeep,
|
||||
(int) (bufferLength - bytesToKeep));
|
||||
|
||||
if (bytesRead < 0)
|
||||
return false;
|
||||
|
||||
lastReadPos += bytesRead;
|
||||
bytesRead += bytesToKeep;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (! source->setPosition (position))
|
||||
return false;
|
||||
|
||||
bytesRead = (int) source->read (buffer, (size_t) bufferLength);
|
||||
|
||||
if (bytesRead < 0)
|
||||
return false;
|
||||
|
||||
lastReadPos = position + bytesRead;
|
||||
}
|
||||
|
||||
bufferedRange = Range<int64> (position, lastReadPos);
|
||||
|
||||
while (bytesRead < bufferLength)
|
||||
buffer[bytesRead++] = 0;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int BufferedInputStream::read (void* destBuffer, const int maxBytesToRead)
|
||||
{
|
||||
const auto initialPosition = position;
|
||||
|
||||
const auto getBufferedRange = [this] { return bufferedRange; };
|
||||
|
||||
const auto readFromReservoir = [this, &destBuffer, &initialPosition] (const Range<int64> rangeToRead)
|
||||
{
|
||||
memcpy (static_cast<char*> (destBuffer) + (rangeToRead.getStart() - initialPosition),
|
||||
buffer + (rangeToRead.getStart() - bufferedRange.getStart()),
|
||||
(size_t) rangeToRead.getLength());
|
||||
};
|
||||
|
||||
const auto fillReservoir = [this] (int64 requestedStart)
|
||||
{
|
||||
position = requestedStart;
|
||||
ensureBuffered();
|
||||
};
|
||||
|
||||
const auto remaining = Reservoir::doBufferedRead (Range<int64> (position, position + maxBytesToRead),
|
||||
getBufferedRange,
|
||||
readFromReservoir,
|
||||
fillReservoir);
|
||||
|
||||
const auto bytesRead = maxBytesToRead - remaining.getLength();
|
||||
position = remaining.getStart();
|
||||
return (int) bytesRead;
|
||||
}
|
||||
|
||||
String BufferedInputStream::readString()
|
||||
{
|
||||
if (position >= bufferedRange.getStart()
|
||||
&& position < lastReadPos)
|
||||
{
|
||||
auto maxChars = (int) (lastReadPos - position);
|
||||
auto* src = buffer + (int) (position - bufferedRange.getStart());
|
||||
|
||||
for (int i = 0; i < maxChars; ++i)
|
||||
{
|
||||
if (src[i] == 0)
|
||||
{
|
||||
position += i + 1;
|
||||
return String::fromUTF8 (src, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return InputStream::readString();
|
||||
}
|
||||
|
||||
|
||||
//==============================================================================
|
||||
//==============================================================================
|
||||
#if JUCE_UNIT_TESTS
|
||||
|
||||
struct BufferedInputStreamTests : public UnitTest
|
||||
{
|
||||
template <typename Fn, size_t... Ix, typename Values>
|
||||
static void applyImpl (Fn&& fn, std::index_sequence<Ix...>, Values&& values)
|
||||
{
|
||||
fn (std::get<Ix> (values)...);
|
||||
}
|
||||
|
||||
template <typename Fn, typename... Values>
|
||||
static void apply (Fn&& fn, std::tuple<Values...> values)
|
||||
{
|
||||
applyImpl (fn, std::make_index_sequence<sizeof... (Values)>(), values);
|
||||
}
|
||||
|
||||
template <typename Fn, typename Values>
|
||||
static void allCombinationsImpl (Fn&& fn, Values&& values)
|
||||
{
|
||||
apply (fn, values);
|
||||
}
|
||||
|
||||
template <typename Fn, typename Values, typename Range, typename... Ranges>
|
||||
static void allCombinationsImpl (Fn&& fn, Values&& values, Range&& range, Ranges&&... ranges)
|
||||
{
|
||||
for (auto& item : range)
|
||||
allCombinationsImpl (fn, std::tuple_cat (values, std::tie (item)), ranges...);
|
||||
}
|
||||
|
||||
template <typename Fn, typename... Ranges>
|
||||
static void allCombinations (Fn&& fn, Ranges&&... ranges)
|
||||
{
|
||||
allCombinationsImpl (fn, std::tie(), ranges...);
|
||||
}
|
||||
|
||||
BufferedInputStreamTests()
|
||||
: UnitTest ("BufferedInputStream", UnitTestCategories::streams)
|
||||
{}
|
||||
|
||||
void runTest() override
|
||||
{
|
||||
const MemoryBlock testBufferA ("abcdefghijklmnopqrstuvwxyz", 26);
|
||||
|
||||
const auto testBufferB = [&]
|
||||
{
|
||||
MemoryBlock mb { 8192 };
|
||||
auto r = getRandom();
|
||||
|
||||
std::for_each (mb.begin(), mb.end(), [&] (char& item)
|
||||
{
|
||||
item = (char) r.nextInt (std::numeric_limits<char>::max());
|
||||
});
|
||||
|
||||
return mb;
|
||||
}();
|
||||
|
||||
const MemoryBlock buffers[] { testBufferA, testBufferB };
|
||||
const int readSizes[] { 3, 10, 50 };
|
||||
const bool shouldPeek[] { false, true };
|
||||
|
||||
const auto runTest = [this] (const MemoryBlock& data, const int readSize, const bool peek)
|
||||
{
|
||||
MemoryInputStream mi (data, true);
|
||||
|
||||
BufferedInputStream stream (mi, jmin (200, (int) data.getSize()));
|
||||
|
||||
beginTest ("Read");
|
||||
|
||||
expectEquals (stream.getPosition(), (int64) 0);
|
||||
expectEquals (stream.getTotalLength(), (int64) data.getSize());
|
||||
expectEquals (stream.getNumBytesRemaining(), stream.getTotalLength());
|
||||
expect (! stream.isExhausted());
|
||||
|
||||
size_t numBytesRead = 0;
|
||||
MemoryBlock readBuffer (data.getSize());
|
||||
|
||||
while (numBytesRead < data.getSize())
|
||||
{
|
||||
if (peek)
|
||||
expectEquals (stream.peekByte(), *(char*) (data.begin() + numBytesRead));
|
||||
|
||||
const auto startingPos = numBytesRead;
|
||||
numBytesRead += (size_t) stream.read (readBuffer.begin() + numBytesRead, readSize);
|
||||
|
||||
expect (std::equal (readBuffer.begin() + startingPos,
|
||||
readBuffer.begin() + numBytesRead,
|
||||
data.begin() + startingPos,
|
||||
data.begin() + numBytesRead));
|
||||
expectEquals (stream.getPosition(), (int64) numBytesRead);
|
||||
expectEquals (stream.getNumBytesRemaining(), (int64) (data.getSize() - numBytesRead));
|
||||
expect (stream.isExhausted() == (numBytesRead == data.getSize()));
|
||||
}
|
||||
|
||||
expectEquals (stream.getPosition(), (int64) data.getSize());
|
||||
expectEquals (stream.getNumBytesRemaining(), (int64) 0);
|
||||
expect (stream.isExhausted());
|
||||
|
||||
expect (readBuffer == data);
|
||||
|
||||
beginTest ("Skip");
|
||||
|
||||
stream.setPosition (0);
|
||||
expectEquals (stream.getPosition(), (int64) 0);
|
||||
expectEquals (stream.getTotalLength(), (int64) data.getSize());
|
||||
expectEquals (stream.getNumBytesRemaining(), stream.getTotalLength());
|
||||
expect (! stream.isExhausted());
|
||||
|
||||
numBytesRead = 0;
|
||||
const int numBytesToSkip = 5;
|
||||
|
||||
while (numBytesRead < data.getSize())
|
||||
{
|
||||
expectEquals (stream.peekByte(), *(char*) (data.begin() + numBytesRead));
|
||||
|
||||
stream.skipNextBytes (numBytesToSkip);
|
||||
numBytesRead += numBytesToSkip;
|
||||
numBytesRead = std::min (numBytesRead, data.getSize());
|
||||
|
||||
expectEquals (stream.getPosition(), (int64) numBytesRead);
|
||||
expectEquals (stream.getNumBytesRemaining(), (int64) (data.getSize() - numBytesRead));
|
||||
expect (stream.isExhausted() == (numBytesRead == data.getSize()));
|
||||
}
|
||||
|
||||
expectEquals (stream.getPosition(), (int64) data.getSize());
|
||||
expectEquals (stream.getNumBytesRemaining(), (int64) 0);
|
||||
expect (stream.isExhausted());
|
||||
};
|
||||
|
||||
allCombinations (runTest, buffers, readSizes, shouldPeek);
|
||||
}
|
||||
};
|
||||
|
||||
static BufferedInputStreamTests bufferedInputStreamTests;
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace juce
|
90
deps/juce/modules/juce_core/streams/juce_BufferedInputStream.h
vendored
Normal file
90
deps/juce/modules/juce_core/streams/juce_BufferedInputStream.h
vendored
Normal file
@ -0,0 +1,90 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
The code included in this file is provided 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.
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
/** Wraps another input stream, and reads from it using an intermediate buffer
|
||||
|
||||
If you're using an input stream such as a file input stream, and making lots of
|
||||
small read accesses to it, it's probably sensible to wrap it in one of these,
|
||||
so that the source stream gets accessed in larger chunk sizes, meaning less
|
||||
work for the underlying stream.
|
||||
|
||||
@tags{Core}
|
||||
*/
|
||||
class JUCE_API BufferedInputStream : public InputStream
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Creates a BufferedInputStream from an input source.
|
||||
|
||||
@param sourceStream the source stream to read from
|
||||
@param bufferSize the size of reservoir to use to buffer the source
|
||||
@param deleteSourceWhenDestroyed whether the sourceStream that is passed in should be
|
||||
deleted by this object when it is itself deleted.
|
||||
*/
|
||||
BufferedInputStream (InputStream* sourceStream,
|
||||
int bufferSize,
|
||||
bool deleteSourceWhenDestroyed);
|
||||
|
||||
/** Creates a BufferedInputStream from an input source.
|
||||
|
||||
@param sourceStream the source stream to read from - the source stream must not
|
||||
be deleted until this object has been destroyed.
|
||||
@param bufferSize the size of reservoir to use to buffer the source
|
||||
*/
|
||||
BufferedInputStream (InputStream& sourceStream, int bufferSize);
|
||||
|
||||
/** Destructor.
|
||||
|
||||
This may also delete the source stream, if that option was chosen when the
|
||||
buffered stream was created.
|
||||
*/
|
||||
~BufferedInputStream() override;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/** Returns the next byte that would be read by a call to readByte() */
|
||||
char peekByte();
|
||||
|
||||
int64 getTotalLength() override;
|
||||
int64 getPosition() override;
|
||||
bool setPosition (int64 newPosition) override;
|
||||
int read (void* destBuffer, int maxBytesToRead) override;
|
||||
String readString() override;
|
||||
bool isExhausted() override;
|
||||
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
OptionalScopedPointer<InputStream> source;
|
||||
Range<int64> bufferedRange;
|
||||
int64 position, bufferLength, lastReadPos = 0, bufferOverlap = 128;
|
||||
HeapBlock<char> buffer;
|
||||
bool ensureBuffered();
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (BufferedInputStream)
|
||||
};
|
||||
|
||||
} // namespace juce
|
55
deps/juce/modules/juce_core/streams/juce_FileInputSource.cpp
vendored
Normal file
55
deps/juce/modules/juce_core/streams/juce_FileInputSource.cpp
vendored
Normal file
@ -0,0 +1,55 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
The code included in this file is provided 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.
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
FileInputSource::FileInputSource (const File& f, bool useFileTimeInHash)
|
||||
: file (f), useFileTimeInHashGeneration (useFileTimeInHash)
|
||||
{
|
||||
}
|
||||
|
||||
FileInputSource::~FileInputSource()
|
||||
{
|
||||
}
|
||||
|
||||
InputStream* FileInputSource::createInputStream()
|
||||
{
|
||||
return file.createInputStream().release();
|
||||
}
|
||||
|
||||
InputStream* FileInputSource::createInputStreamFor (const String& relatedItemPath)
|
||||
{
|
||||
return file.getSiblingFile (relatedItemPath).createInputStream().release();
|
||||
}
|
||||
|
||||
int64 FileInputSource::hashCode() const
|
||||
{
|
||||
int64 h = file.hashCode();
|
||||
|
||||
if (useFileTimeInHashGeneration)
|
||||
h ^= file.getLastModificationTime().toMilliseconds();
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
} // namespace juce
|
60
deps/juce/modules/juce_core/streams/juce_FileInputSource.h
vendored
Normal file
60
deps/juce/modules/juce_core/streams/juce_FileInputSource.h
vendored
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
The code included in this file is provided 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.
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
A type of InputSource that represents a normal file.
|
||||
|
||||
@see InputSource
|
||||
|
||||
@tags{Core}
|
||||
*/
|
||||
class JUCE_API FileInputSource : public InputSource
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Creates a FileInputSource for a file.
|
||||
If the useFileTimeInHashGeneration parameter is true, then this object's
|
||||
hashCode() method will incorporate the file time into its hash code; if
|
||||
false, only the file name will be used for the hash.
|
||||
*/
|
||||
FileInputSource (const File& file, bool useFileTimeInHashGeneration = false);
|
||||
|
||||
/** Destructor. */
|
||||
~FileInputSource() override;
|
||||
|
||||
InputStream* createInputStream() override;
|
||||
InputStream* createInputStreamFor (const String& relatedItemPath) override;
|
||||
int64 hashCode() const override;
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
const File file;
|
||||
bool useFileTimeInHashGeneration;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (FileInputSource)
|
||||
};
|
||||
|
||||
}
|
72
deps/juce/modules/juce_core/streams/juce_InputSource.h
vendored
Normal file
72
deps/juce/modules/juce_core/streams/juce_InputSource.h
vendored
Normal file
@ -0,0 +1,72 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
The code included in this file is provided 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.
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
A lightweight object that can create a stream to read some kind of resource.
|
||||
|
||||
This may be used to refer to a file, or some other kind of source, allowing a
|
||||
caller to create an input stream that can read from it when required.
|
||||
|
||||
@see FileInputSource
|
||||
|
||||
@tags{Core}
|
||||
*/
|
||||
class JUCE_API InputSource
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
InputSource() = default;
|
||||
|
||||
/** Destructor. */
|
||||
virtual ~InputSource() = default;
|
||||
|
||||
//==============================================================================
|
||||
/** Returns a new InputStream to read this item.
|
||||
|
||||
@returns an inputstream that the caller will delete, or nullptr if
|
||||
the filename isn't found.
|
||||
*/
|
||||
virtual InputStream* createInputStream() = 0;
|
||||
|
||||
/** Returns a new InputStream to read an item, relative.
|
||||
|
||||
@param relatedItemPath the relative pathname of the resource that is required
|
||||
@returns an inputstream that the caller will delete, or nullptr if
|
||||
the item isn't found.
|
||||
*/
|
||||
virtual InputStream* createInputStreamFor (const String& relatedItemPath) = 0;
|
||||
|
||||
/** Returns a hash code that uniquely represents this item.
|
||||
*/
|
||||
virtual int64 hashCode() const = 0;
|
||||
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
JUCE_LEAK_DETECTOR (InputSource)
|
||||
};
|
||||
|
||||
} // namespace juce
|
249
deps/juce/modules/juce_core/streams/juce_InputStream.cpp
vendored
Normal file
249
deps/juce/modules/juce_core/streams/juce_InputStream.cpp
vendored
Normal file
@ -0,0 +1,249 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
The code included in this file is provided 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.
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
int64 InputStream::getNumBytesRemaining()
|
||||
{
|
||||
auto len = getTotalLength();
|
||||
|
||||
if (len >= 0)
|
||||
len -= getPosition();
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
ssize_t InputStream::read (void* destBuffer, size_t size)
|
||||
{
|
||||
ssize_t totalRead = 0;
|
||||
|
||||
while (size > 0)
|
||||
{
|
||||
auto numToRead = (int) std::min (size, (size_t) 0x70000000);
|
||||
auto numRead = read (juce::addBytesToPointer (destBuffer, totalRead), numToRead);
|
||||
jassert (numRead <= numToRead);
|
||||
|
||||
if (numRead < 0) return (ssize_t) numRead;
|
||||
if (numRead == 0) break;
|
||||
|
||||
size -= (size_t) numRead;
|
||||
totalRead += numRead;
|
||||
}
|
||||
|
||||
return totalRead;
|
||||
}
|
||||
|
||||
char InputStream::readByte()
|
||||
{
|
||||
char temp = 0;
|
||||
read (&temp, 1);
|
||||
return temp;
|
||||
}
|
||||
|
||||
bool InputStream::readBool()
|
||||
{
|
||||
return readByte() != 0;
|
||||
}
|
||||
|
||||
short InputStream::readShort()
|
||||
{
|
||||
char temp[2];
|
||||
|
||||
if (read (temp, 2) == 2)
|
||||
return (short) ByteOrder::littleEndianShort (temp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
short InputStream::readShortBigEndian()
|
||||
{
|
||||
char temp[2];
|
||||
|
||||
if (read (temp, 2) == 2)
|
||||
return (short) ByteOrder::bigEndianShort (temp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int InputStream::readInt()
|
||||
{
|
||||
char temp[4];
|
||||
|
||||
if (read (temp, 4) == 4)
|
||||
return (int) ByteOrder::littleEndianInt (temp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int InputStream::readIntBigEndian()
|
||||
{
|
||||
char temp[4];
|
||||
|
||||
if (read (temp, 4) == 4)
|
||||
return (int) ByteOrder::bigEndianInt (temp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int InputStream::readCompressedInt()
|
||||
{
|
||||
auto sizeByte = (uint8) readByte();
|
||||
|
||||
if (sizeByte == 0)
|
||||
return 0;
|
||||
|
||||
const int numBytes = (sizeByte & 0x7f);
|
||||
|
||||
if (numBytes > 4)
|
||||
{
|
||||
jassertfalse; // trying to read corrupt data - this method must only be used
|
||||
// to read data that was written by OutputStream::writeCompressedInt()
|
||||
return 0;
|
||||
}
|
||||
|
||||
char bytes[4] = {};
|
||||
|
||||
if (read (bytes, numBytes) != numBytes)
|
||||
return 0;
|
||||
|
||||
auto num = (int) ByteOrder::littleEndianInt (bytes);
|
||||
return (sizeByte >> 7) ? -num : num;
|
||||
}
|
||||
|
||||
int64 InputStream::readInt64()
|
||||
{
|
||||
union { uint8 asBytes[8]; uint64 asInt64; } n;
|
||||
|
||||
if (read (n.asBytes, 8) == 8)
|
||||
return (int64) ByteOrder::swapIfBigEndian (n.asInt64);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int64 InputStream::readInt64BigEndian()
|
||||
{
|
||||
union { uint8 asBytes[8]; uint64 asInt64; } n;
|
||||
|
||||
if (read (n.asBytes, 8) == 8)
|
||||
return (int64) ByteOrder::swapIfLittleEndian (n.asInt64);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
float InputStream::readFloat()
|
||||
{
|
||||
static_assert (sizeof (int32) == sizeof (float), "Union assumes float has the same size as an int32");
|
||||
union { int32 asInt; float asFloat; } n;
|
||||
n.asInt = (int32) readInt();
|
||||
return n.asFloat;
|
||||
}
|
||||
|
||||
float InputStream::readFloatBigEndian()
|
||||
{
|
||||
union { int32 asInt; float asFloat; } n;
|
||||
n.asInt = (int32) readIntBigEndian();
|
||||
return n.asFloat;
|
||||
}
|
||||
|
||||
double InputStream::readDouble()
|
||||
{
|
||||
union { int64 asInt; double asDouble; } n;
|
||||
n.asInt = readInt64();
|
||||
return n.asDouble;
|
||||
}
|
||||
|
||||
double InputStream::readDoubleBigEndian()
|
||||
{
|
||||
union { int64 asInt; double asDouble; } n;
|
||||
n.asInt = readInt64BigEndian();
|
||||
return n.asDouble;
|
||||
}
|
||||
|
||||
String InputStream::readString()
|
||||
{
|
||||
MemoryOutputStream buffer;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
auto c = readByte();
|
||||
buffer.writeByte (c);
|
||||
|
||||
if (c == 0)
|
||||
return buffer.toUTF8();
|
||||
}
|
||||
}
|
||||
|
||||
String InputStream::readNextLine()
|
||||
{
|
||||
MemoryOutputStream buffer;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
auto c = readByte();
|
||||
|
||||
if (c == 0 || c == '\n')
|
||||
break;
|
||||
|
||||
if (c == '\r')
|
||||
{
|
||||
auto lastPos = getPosition();
|
||||
|
||||
if (readByte() != '\n')
|
||||
setPosition (lastPos);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
buffer.writeByte (c);
|
||||
}
|
||||
|
||||
return buffer.toUTF8();
|
||||
}
|
||||
|
||||
size_t InputStream::readIntoMemoryBlock (MemoryBlock& block, ssize_t numBytes)
|
||||
{
|
||||
MemoryOutputStream mo (block, true);
|
||||
return (size_t) mo.writeFromInputStream (*this, numBytes);
|
||||
}
|
||||
|
||||
String InputStream::readEntireStreamAsString()
|
||||
{
|
||||
MemoryOutputStream mo;
|
||||
mo << *this;
|
||||
return mo.toString();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void InputStream::skipNextBytes (int64 numBytesToSkip)
|
||||
{
|
||||
if (numBytesToSkip > 0)
|
||||
{
|
||||
auto skipBufferSize = (int) jmin (numBytesToSkip, (int64) 16384);
|
||||
HeapBlock<char> temp (skipBufferSize);
|
||||
|
||||
while (numBytesToSkip > 0 && ! isExhausted())
|
||||
numBytesToSkip -= read (temp, (int) jmin (numBytesToSkip, (int64) skipBufferSize));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace juce
|
264
deps/juce/modules/juce_core/streams/juce_InputStream.h
vendored
Normal file
264
deps/juce/modules/juce_core/streams/juce_InputStream.h
vendored
Normal file
@ -0,0 +1,264 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
The code included in this file is provided 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.
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
/** The base class for streams that read data.
|
||||
|
||||
Input and output streams are used throughout the library - subclasses can override
|
||||
some or all of the virtual functions to implement their behaviour.
|
||||
|
||||
@see OutputStream, MemoryInputStream, BufferedInputStream, FileInputStream
|
||||
|
||||
@tags{Core}
|
||||
*/
|
||||
class JUCE_API InputStream
|
||||
{
|
||||
public:
|
||||
/** Destructor. */
|
||||
virtual ~InputStream() = default;
|
||||
|
||||
//==============================================================================
|
||||
/** Returns the total number of bytes available for reading in this stream.
|
||||
|
||||
Note that this is the number of bytes available from the start of the
|
||||
stream, not from the current position.
|
||||
|
||||
If the size of the stream isn't actually known, this will return -1.
|
||||
|
||||
@see getNumBytesRemaining
|
||||
*/
|
||||
virtual int64 getTotalLength() = 0;
|
||||
|
||||
/** Returns the number of bytes available for reading, or a negative value if
|
||||
the remaining length is not known.
|
||||
@see getTotalLength
|
||||
*/
|
||||
int64 getNumBytesRemaining();
|
||||
|
||||
/** Returns true if the stream has no more data to read. */
|
||||
virtual bool isExhausted() = 0;
|
||||
|
||||
//==============================================================================
|
||||
/** Reads some data from the stream into a memory buffer.
|
||||
|
||||
This is the only read method that subclasses actually need to implement, as the
|
||||
InputStream base class implements the other read methods in terms of this one (although
|
||||
it's often more efficient for subclasses to implement them directly).
|
||||
|
||||
@param destBuffer the destination buffer for the data. This must not be null.
|
||||
@param maxBytesToRead the maximum number of bytes to read - make sure the
|
||||
memory block passed in is big enough to contain this
|
||||
many bytes. This value must not be negative.
|
||||
|
||||
@returns the actual number of bytes that were read, which may be less than
|
||||
maxBytesToRead if the stream is exhausted before it gets that far
|
||||
*/
|
||||
virtual int read (void* destBuffer, int maxBytesToRead) = 0;
|
||||
|
||||
ssize_t read (void* destBuffer, size_t maxBytesToRead);
|
||||
|
||||
/** 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 - 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 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 stream is exhausted partway through reading the bytes, this will return zero.
|
||||
@see OutputStream::writeShortBigEndian, readShort
|
||||
*/
|
||||
virtual short readShortBigEndian();
|
||||
|
||||
/** Reads four bytes from the stream as a little-endian 32-bit value.
|
||||
|
||||
If the next four bytes are byte1 to byte4, this returns
|
||||
(byte1 | (byte2 << 8) | (byte3 << 16) | (byte4 << 24)).
|
||||
|
||||
If the stream is exhausted partway through reading the bytes, this will return zero.
|
||||
|
||||
@see OutputStream::writeInt, readIntBigEndian
|
||||
*/
|
||||
virtual int readInt();
|
||||
|
||||
/** Reads four bytes from the stream as a big-endian 32-bit value.
|
||||
|
||||
If the next four bytes are byte1 to byte4, this returns
|
||||
(byte4 | (byte3 << 8) | (byte2 << 16) | (byte1 << 24)).
|
||||
|
||||
If the stream is exhausted partway through reading the bytes, this will return zero.
|
||||
|
||||
@see OutputStream::writeIntBigEndian, readInt
|
||||
*/
|
||||
virtual int readIntBigEndian();
|
||||
|
||||
/** Reads eight bytes from the stream as a little-endian 64-bit value.
|
||||
|
||||
If the next eight bytes are byte1 to byte8, this returns
|
||||
(byte1 | (byte2 << 8) | (byte3 << 16) | (byte4 << 24) | (byte5 << 32) | (byte6 << 40) | (byte7 << 48) | (byte8 << 56)).
|
||||
|
||||
If the stream is exhausted partway through reading the bytes, this will return zero.
|
||||
|
||||
@see OutputStream::writeInt64, readInt64BigEndian
|
||||
*/
|
||||
virtual int64 readInt64();
|
||||
|
||||
/** Reads eight bytes from the stream as a big-endian 64-bit value.
|
||||
|
||||
If the next eight bytes are byte1 to byte8, this returns
|
||||
(byte8 | (byte7 << 8) | (byte6 << 16) | (byte5 << 24) | (byte4 << 32) | (byte3 << 40) | (byte2 << 48) | (byte1 << 56)).
|
||||
|
||||
If the stream is exhausted partway through reading the bytes, this will return zero.
|
||||
|
||||
@see OutputStream::writeInt64BigEndian, readInt64
|
||||
*/
|
||||
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();
|
||||
|
||||
//==============================================================================
|
||||
/** Reads a UTF-8 string from the stream, up to the next linefeed or carriage return.
|
||||
|
||||
This will read up to the next "\n" or "\r\n" or end-of-stream.
|
||||
|
||||
After this call, the stream's position will be left pointing to the next character
|
||||
following the line-feed, but the linefeeds aren't included in the string that
|
||||
is returned.
|
||||
*/
|
||||
virtual String readNextLine();
|
||||
|
||||
/** Reads a zero-terminated UTF-8 string from the stream.
|
||||
|
||||
This will read characters from the stream until it hits a null character
|
||||
or end-of-stream.
|
||||
|
||||
@see OutputStream::writeString, readEntireStreamAsString
|
||||
*/
|
||||
virtual String readString();
|
||||
|
||||
/** Tries to read the whole stream and turn it into a string.
|
||||
|
||||
This will read from the stream's current position until the end-of-stream.
|
||||
It can read from UTF-8 data, or UTF-16 if it detects suitable header-bytes.
|
||||
*/
|
||||
virtual String readEntireStreamAsString();
|
||||
|
||||
/** Reads from the stream and appends the data to a MemoryBlock.
|
||||
|
||||
@param destBlock the block to append the data onto
|
||||
@param maxNumBytesToRead if this is a positive value, it sets a limit to the number
|
||||
of bytes that will be read - if it's negative, data
|
||||
will be read until the stream is exhausted.
|
||||
@returns the number of bytes that were added to the memory block
|
||||
*/
|
||||
virtual size_t readIntoMemoryBlock (MemoryBlock& destBlock,
|
||||
ssize_t maxNumBytesToRead = -1);
|
||||
|
||||
//==============================================================================
|
||||
/** Returns the offset of the next byte that will be read from the stream.
|
||||
@see setPosition
|
||||
*/
|
||||
virtual int64 getPosition() = 0;
|
||||
|
||||
/** Tries to move the current read position of the stream.
|
||||
|
||||
The position is an absolute number of bytes from the stream's start.
|
||||
|
||||
Some streams might not be able to do this, in which case they should do
|
||||
nothing and return false. Others might be able to manage it by resetting
|
||||
themselves and skipping to the correct position, although this is
|
||||
obviously a bit slow.
|
||||
|
||||
@returns true if the stream manages to reposition itself correctly
|
||||
@see getPosition
|
||||
*/
|
||||
virtual bool setPosition (int64 newPosition) = 0;
|
||||
|
||||
/** Reads and discards a number of bytes from the stream.
|
||||
|
||||
Some input streams might implement this more efficiently, but the base
|
||||
class will just keep reading data until the requisite number of bytes
|
||||
have been done. For large skips it may be quicker to call setPosition()
|
||||
with the required position.
|
||||
*/
|
||||
virtual void skipNextBytes (int64 numBytesToSkip);
|
||||
|
||||
|
||||
protected:
|
||||
//==============================================================================
|
||||
InputStream() = default;
|
||||
|
||||
private:
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (InputStream)
|
||||
};
|
||||
|
||||
} // namespace juce
|
225
deps/juce/modules/juce_core/streams/juce_MemoryInputStream.cpp
vendored
Normal file
225
deps/juce/modules/juce_core/streams/juce_MemoryInputStream.cpp
vendored
Normal file
@ -0,0 +1,225 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
The code included in this file is provided 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.
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
MemoryInputStream::MemoryInputStream (const void* sourceData, size_t sourceDataSize, bool keepCopy)
|
||||
: data (sourceData),
|
||||
dataSize (sourceDataSize)
|
||||
{
|
||||
if (keepCopy)
|
||||
{
|
||||
internalCopy = MemoryBlock (sourceData, sourceDataSize);
|
||||
data = internalCopy.getData();
|
||||
}
|
||||
}
|
||||
|
||||
MemoryInputStream::MemoryInputStream (const MemoryBlock& sourceData, bool keepCopy)
|
||||
: data (sourceData.getData()),
|
||||
dataSize (sourceData.getSize())
|
||||
{
|
||||
if (keepCopy)
|
||||
{
|
||||
internalCopy = sourceData;
|
||||
data = internalCopy.getData();
|
||||
}
|
||||
}
|
||||
|
||||
MemoryInputStream::MemoryInputStream (MemoryBlock&& source)
|
||||
: internalCopy (std::move (source))
|
||||
{
|
||||
data = internalCopy.getData();
|
||||
dataSize = internalCopy.getSize();
|
||||
}
|
||||
|
||||
MemoryInputStream::~MemoryInputStream() = default;
|
||||
|
||||
int64 MemoryInputStream::getTotalLength()
|
||||
{
|
||||
return (int64) dataSize;
|
||||
}
|
||||
|
||||
int MemoryInputStream::read (void* buffer, int howMany)
|
||||
{
|
||||
jassert (buffer != nullptr && howMany >= 0);
|
||||
|
||||
if (howMany <= 0 || position >= dataSize)
|
||||
return 0;
|
||||
|
||||
auto 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;
|
||||
}
|
||||
|
||||
void MemoryInputStream::skipNextBytes (int64 numBytesToSkip)
|
||||
{
|
||||
if (numBytesToSkip > 0)
|
||||
setPosition (getPosition() + numBytesToSkip);
|
||||
}
|
||||
|
||||
|
||||
//==============================================================================
|
||||
//==============================================================================
|
||||
#if JUCE_UNIT_TESTS
|
||||
|
||||
class MemoryStreamTests : public UnitTest
|
||||
{
|
||||
public:
|
||||
MemoryStreamTests()
|
||||
: UnitTest ("MemoryInputStream & MemoryOutputStream", UnitTestCategories::streams)
|
||||
{}
|
||||
|
||||
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);
|
||||
|
||||
const MemoryBlock data ("abcdefghijklmnopqrstuvwxyz", 26);
|
||||
MemoryInputStream stream (data, true);
|
||||
|
||||
beginTest ("Read");
|
||||
|
||||
expectEquals (stream.getPosition(), (int64) 0);
|
||||
expectEquals (stream.getTotalLength(), (int64) data.getSize());
|
||||
expectEquals (stream.getNumBytesRemaining(), stream.getTotalLength());
|
||||
expect (! stream.isExhausted());
|
||||
|
||||
size_t numBytesRead = 0;
|
||||
MemoryBlock readBuffer (data.getSize());
|
||||
|
||||
while (numBytesRead < data.getSize())
|
||||
{
|
||||
numBytesRead += (size_t) stream.read (&readBuffer[numBytesRead], 3);
|
||||
|
||||
expectEquals (stream.getPosition(), (int64) numBytesRead);
|
||||
expectEquals (stream.getNumBytesRemaining(), (int64) (data.getSize() - numBytesRead));
|
||||
expect (stream.isExhausted() == (numBytesRead == data.getSize()));
|
||||
}
|
||||
|
||||
expectEquals (stream.getPosition(), (int64) data.getSize());
|
||||
expectEquals (stream.getNumBytesRemaining(), (int64) 0);
|
||||
expect (stream.isExhausted());
|
||||
|
||||
expect (readBuffer == data);
|
||||
|
||||
beginTest ("Skip");
|
||||
|
||||
stream.setPosition (0);
|
||||
expectEquals (stream.getPosition(), (int64) 0);
|
||||
expectEquals (stream.getTotalLength(), (int64) data.getSize());
|
||||
expectEquals (stream.getNumBytesRemaining(), stream.getTotalLength());
|
||||
expect (! stream.isExhausted());
|
||||
|
||||
numBytesRead = 0;
|
||||
const int numBytesToSkip = 5;
|
||||
|
||||
while (numBytesRead < data.getSize())
|
||||
{
|
||||
stream.skipNextBytes (numBytesToSkip);
|
||||
numBytesRead += numBytesToSkip;
|
||||
numBytesRead = std::min (numBytesRead, data.getSize());
|
||||
|
||||
expectEquals (stream.getPosition(), (int64) numBytesRead);
|
||||
expectEquals (stream.getNumBytesRemaining(), (int64) (data.getSize() - numBytesRead));
|
||||
expect (stream.isExhausted() == (numBytesRead == data.getSize()));
|
||||
}
|
||||
|
||||
expectEquals (stream.getPosition(), (int64) data.getSize());
|
||||
expectEquals (stream.getNumBytesRemaining(), (int64) 0);
|
||||
expect (stream.isExhausted());
|
||||
}
|
||||
|
||||
static String createRandomWideCharString (Random& r)
|
||||
{
|
||||
juce_wchar buffer [50] = { 0 };
|
||||
|
||||
for (int i = 0; i < numElementsInArray (buffer) - 1; ++i)
|
||||
{
|
||||
if (r.nextBool())
|
||||
{
|
||||
do
|
||||
{
|
||||
buffer[i] = (juce_wchar) (1 + r.nextInt (0x10ffff - 1));
|
||||
}
|
||||
while (! CharPointer_UTF16::canRepresent (buffer[i]));
|
||||
}
|
||||
else
|
||||
buffer[i] = (juce_wchar) (1 + r.nextInt (0xff));
|
||||
}
|
||||
|
||||
return CharPointer_UTF32 (buffer);
|
||||
}
|
||||
};
|
||||
|
||||
static MemoryStreamTests memoryInputStreamUnitTests;
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace juce
|
94
deps/juce/modules/juce_core/streams/juce_MemoryInputStream.h
vendored
Normal file
94
deps/juce/modules/juce_core/streams/juce_MemoryInputStream.h
vendored
Normal file
@ -0,0 +1,94 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
The code included in this file is provided 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.
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
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.
|
||||
|
||||
@tags{Core}
|
||||
*/
|
||||
class JUCE_API 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);
|
||||
|
||||
/** Creates a stream by moving from a MemoryBlock. */
|
||||
MemoryInputStream (MemoryBlock&& blockToTake);
|
||||
|
||||
/** Destructor. */
|
||||
~MemoryInputStream() override;
|
||||
|
||||
/** 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) override;
|
||||
int64 getTotalLength() override;
|
||||
bool isExhausted() override;
|
||||
int read (void* destBuffer, int maxBytesToRead) override;
|
||||
void skipNextBytes (int64 numBytesToSkip) override;
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
const void* data;
|
||||
size_t dataSize, position = 0;
|
||||
MemoryBlock internalCopy;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MemoryInputStream)
|
||||
};
|
||||
|
||||
} // namespace juce
|
210
deps/juce/modules/juce_core/streams/juce_MemoryOutputStream.cpp
vendored
Normal file
210
deps/juce/modules/juce_core/streams/juce_MemoryOutputStream.cpp
vendored
Normal file
@ -0,0 +1,210 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
The code included in this file is provided 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.
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
MemoryOutputStream::MemoryOutputStream (const size_t initialSize)
|
||||
: blockToUse (&internalBlock)
|
||||
{
|
||||
internalBlock.setSize (initialSize, false);
|
||||
}
|
||||
|
||||
MemoryOutputStream::MemoryOutputStream (MemoryBlock& memoryBlockToWriteTo,
|
||||
const bool appendToExistingBlockContent)
|
||||
: blockToUse (&memoryBlockToWriteTo)
|
||||
{
|
||||
if (appendToExistingBlockContent)
|
||||
position = size = memoryBlockToWriteTo.getSize();
|
||||
}
|
||||
|
||||
MemoryOutputStream::MemoryOutputStream (void* destBuffer, size_t destBufferSize)
|
||||
: externalData (destBuffer), availableSize (destBufferSize)
|
||||
{
|
||||
jassert (externalData != nullptr); // This must be a valid pointer.
|
||||
}
|
||||
|
||||
MemoryOutputStream::~MemoryOutputStream()
|
||||
{
|
||||
trimExternalBlockSize();
|
||||
}
|
||||
|
||||
void MemoryOutputStream::flush()
|
||||
{
|
||||
trimExternalBlockSize();
|
||||
}
|
||||
|
||||
void MemoryOutputStream::trimExternalBlockSize()
|
||||
{
|
||||
if (blockToUse != &internalBlock && blockToUse != nullptr)
|
||||
blockToUse->setSize (size, false);
|
||||
}
|
||||
|
||||
void MemoryOutputStream::preallocate (const size_t bytesToPreallocate)
|
||||
{
|
||||
if (blockToUse != nullptr)
|
||||
blockToUse->ensureSize (bytesToPreallocate + 1);
|
||||
}
|
||||
|
||||
void MemoryOutputStream::reset() noexcept
|
||||
{
|
||||
position = 0;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
char* MemoryOutputStream::prepareToWrite (size_t numBytes)
|
||||
{
|
||||
jassert ((ssize_t) numBytes >= 0);
|
||||
auto storageNeeded = position + numBytes;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
auto* writePointer = data + position;
|
||||
position += numBytes;
|
||||
size = jmax (size, position);
|
||||
return writePointer;
|
||||
}
|
||||
|
||||
bool MemoryOutputStream::write (const void* const buffer, size_t howMany)
|
||||
{
|
||||
if (howMany == 0)
|
||||
return true;
|
||||
|
||||
jassert (buffer != nullptr);
|
||||
|
||||
if (auto* dest = prepareToWrite (howMany))
|
||||
{
|
||||
memcpy (dest, buffer, howMany);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MemoryOutputStream::writeRepeatedByte (uint8 byte, size_t howMany)
|
||||
{
|
||||
if (howMany == 0)
|
||||
return true;
|
||||
|
||||
if (auto* dest = prepareToWrite (howMany))
|
||||
{
|
||||
memset (dest, byte, howMany);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MemoryOutputStream::appendUTF8Char (juce_wchar c)
|
||||
{
|
||||
if (auto* dest = prepareToWrite (CharPointer_UTF8::getBytesRequiredFor (c)))
|
||||
{
|
||||
CharPointer_UTF8 (dest).write (c);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
MemoryBlock MemoryOutputStream::getMemoryBlock() const
|
||||
{
|
||||
return MemoryBlock (getData(), getDataSize());
|
||||
}
|
||||
|
||||
const void* MemoryOutputStream::getData() const noexcept
|
||||
{
|
||||
if (blockToUse == nullptr)
|
||||
return externalData;
|
||||
|
||||
if (blockToUse->getSize() > size)
|
||||
static_cast<char*> (blockToUse->getData()) [size] = 0;
|
||||
|
||||
return blockToUse->getData();
|
||||
}
|
||||
|
||||
bool MemoryOutputStream::setPosition (int64 newPosition)
|
||||
{
|
||||
if (newPosition <= (int64) size)
|
||||
{
|
||||
// ok to seek backwards
|
||||
position = jlimit ((size_t) 0, size, (size_t) newPosition);
|
||||
return true;
|
||||
}
|
||||
|
||||
// can't move beyond the end of the stream..
|
||||
return false;
|
||||
}
|
||||
|
||||
int64 MemoryOutputStream::writeFromInputStream (InputStream& source, int64 maxNumBytesToWrite)
|
||||
{
|
||||
// before writing from an input, see if we can preallocate to make it more efficient..
|
||||
int64 availableData = source.getTotalLength() - source.getPosition();
|
||||
|
||||
if (availableData > 0)
|
||||
{
|
||||
if (maxNumBytesToWrite > availableData || maxNumBytesToWrite < 0)
|
||||
maxNumBytesToWrite = availableData;
|
||||
|
||||
if (blockToUse != nullptr)
|
||||
preallocate (blockToUse->getSize() + (size_t) maxNumBytesToWrite);
|
||||
}
|
||||
|
||||
return OutputStream::writeFromInputStream (source, maxNumBytesToWrite);
|
||||
}
|
||||
|
||||
String MemoryOutputStream::toUTF8() const
|
||||
{
|
||||
auto* d = static_cast<const char*> (getData());
|
||||
return String (CharPointer_UTF8 (d), CharPointer_UTF8 (d + getDataSize()));
|
||||
}
|
||||
|
||||
String MemoryOutputStream::toString() const
|
||||
{
|
||||
return String::createStringFromData (getData(), (int) getDataSize());
|
||||
}
|
||||
|
||||
OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const MemoryOutputStream& streamToRead)
|
||||
{
|
||||
auto dataSize = streamToRead.getDataSize();
|
||||
|
||||
if (dataSize > 0)
|
||||
stream.write (streamToRead.getData(), dataSize);
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
} // namespace juce
|
133
deps/juce/modules/juce_core/streams/juce_MemoryOutputStream.h
vendored
Normal file
133
deps/juce/modules/juce_core/streams/juce_MemoryOutputStream.h
vendored
Normal file
@ -0,0 +1,133 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
The code included in this file is provided 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.
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
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.
|
||||
|
||||
@tags{Core}
|
||||
*/
|
||||
class JUCE_API MemoryOutputStream : public OutputStream
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Creates an empty memory stream, ready to be written into.
|
||||
@param initialSize the initial amount of capacity to allocate for writing into
|
||||
*/
|
||||
MemoryOutputStream (size_t initialSize = 256);
|
||||
|
||||
/** Creates a memory stream for writing into into a pre-existing MemoryBlock object.
|
||||
|
||||
Note that the destination block will always be larger than the amount of data
|
||||
that has been written to the stream, because the MemoryOutputStream keeps some
|
||||
spare capacity at its end. To trim the block's size down to fit the actual
|
||||
data, call flush(), or delete the MemoryOutputStream.
|
||||
|
||||
@param memoryBlockToWriteTo the block into which new data will be written.
|
||||
@param appendToExistingBlockContent if this is true, the contents of the block will be
|
||||
kept, and new data will be appended to it. If false,
|
||||
the block will be cleared before use
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
~MemoryOutputStream() override;
|
||||
|
||||
//==============================================================================
|
||||
/** Returns a pointer to the data that has been written to the stream.
|
||||
@see getDataSize
|
||||
*/
|
||||
const void* getData() const noexcept;
|
||||
|
||||
/** Returns the number of bytes of data that have been written to the stream.
|
||||
@see getData
|
||||
*/
|
||||
size_t getDataSize() const noexcept { return size; }
|
||||
|
||||
/** Resets the stream, clearing any data that has been written to it so far. */
|
||||
void reset() noexcept;
|
||||
|
||||
/** Increases the internal storage capacity to be able to contain at least the specified
|
||||
amount of data without needing to be resized.
|
||||
*/
|
||||
void preallocate (size_t bytesToPreallocate);
|
||||
|
||||
/** Appends the utf-8 bytes for a unicode character */
|
||||
bool appendUTF8Char (juce_wchar character);
|
||||
|
||||
/** Returns a String created from the (UTF8) data that has been written to the stream. */
|
||||
String toUTF8() const;
|
||||
|
||||
/** Attempts to detect the encoding of the data and convert it to a string.
|
||||
@see String::createStringFromData
|
||||
*/
|
||||
String toString() const;
|
||||
|
||||
/** Returns a copy of the stream's data as a memory block. */
|
||||
MemoryBlock getMemoryBlock() const;
|
||||
|
||||
//==============================================================================
|
||||
/** If the stream is writing to a user-supplied MemoryBlock, this will trim any excess
|
||||
capacity off the block, so that its length matches the amount of actual data that
|
||||
has been written so far.
|
||||
*/
|
||||
void flush() override;
|
||||
|
||||
bool write (const void*, size_t) override;
|
||||
int64 getPosition() override { return (int64) position; }
|
||||
bool setPosition (int64) override;
|
||||
int64 writeFromInputStream (InputStream&, int64 maxNumBytesToWrite) override;
|
||||
bool writeRepeatedByte (uint8 byte, size_t numTimesToRepeat) override;
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
MemoryBlock* const blockToUse = nullptr;
|
||||
MemoryBlock internalBlock;
|
||||
void* externalData = nullptr;
|
||||
size_t position = 0, size = 0, availableSize = 0;
|
||||
|
||||
void trimExternalBlockSize();
|
||||
char* prepareToWrite (size_t);
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MemoryOutputStream)
|
||||
};
|
||||
|
||||
/** Copies all the data that has been written to a MemoryOutputStream into another stream. */
|
||||
OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const MemoryOutputStream& streamToRead);
|
||||
|
||||
} // namespace juce
|
394
deps/juce/modules/juce_core/streams/juce_OutputStream.cpp
vendored
Normal file
394
deps/juce/modules/juce_core/streams/juce_OutputStream.cpp
vendored
Normal file
@ -0,0 +1,394 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
The code included in this file is provided 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.
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
#if JUCE_DEBUG
|
||||
|
||||
//==============================================================================
|
||||
struct DanglingStreamChecker
|
||||
{
|
||||
DanglingStreamChecker() = default;
|
||||
|
||||
~DanglingStreamChecker()
|
||||
{
|
||||
/*
|
||||
It's always a bad idea to leak any object, but if you're leaking output
|
||||
streams, then there's a good chance that you're failing to flush a file
|
||||
to disk properly, which could result in corrupted data and other similar
|
||||
nastiness..
|
||||
*/
|
||||
jassert (activeStreams.size() == 0);
|
||||
|
||||
// We need to flag when this helper struct has been destroyed to prevent some
|
||||
// nasty order-of-static-destruction issues
|
||||
hasBeenDestroyed = true;
|
||||
}
|
||||
|
||||
Array<void*, CriticalSection> activeStreams;
|
||||
|
||||
static bool hasBeenDestroyed;
|
||||
};
|
||||
|
||||
bool DanglingStreamChecker::hasBeenDestroyed = false;
|
||||
static DanglingStreamChecker danglingStreamChecker;
|
||||
|
||||
#endif
|
||||
|
||||
//==============================================================================
|
||||
OutputStream::OutputStream()
|
||||
: newLineString (NewLine::getDefault())
|
||||
{
|
||||
#if JUCE_DEBUG
|
||||
if (! DanglingStreamChecker::hasBeenDestroyed)
|
||||
danglingStreamChecker.activeStreams.add (this);
|
||||
#endif
|
||||
}
|
||||
|
||||
OutputStream::~OutputStream()
|
||||
{
|
||||
#if JUCE_DEBUG
|
||||
if (! DanglingStreamChecker::hasBeenDestroyed)
|
||||
danglingStreamChecker.activeStreams.removeFirstMatchingValue (this);
|
||||
#endif
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
bool OutputStream::writeBool (bool b)
|
||||
{
|
||||
return writeByte (b ? (char) 1
|
||||
: (char) 0);
|
||||
}
|
||||
|
||||
bool OutputStream::writeByte (char byte)
|
||||
{
|
||||
return write (&byte, 1);
|
||||
}
|
||||
|
||||
bool OutputStream::writeRepeatedByte (uint8 byte, size_t numTimesToRepeat)
|
||||
{
|
||||
for (size_t i = 0; i < numTimesToRepeat; ++i)
|
||||
if (! writeByte ((char) byte))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OutputStream::writeShort (short value)
|
||||
{
|
||||
auto v = ByteOrder::swapIfBigEndian ((uint16) value);
|
||||
return write (&v, 2);
|
||||
}
|
||||
|
||||
bool OutputStream::writeShortBigEndian (short value)
|
||||
{
|
||||
auto v = ByteOrder::swapIfLittleEndian ((uint16) value);
|
||||
return write (&v, 2);
|
||||
}
|
||||
|
||||
bool OutputStream::writeInt (int value)
|
||||
{
|
||||
auto v = ByteOrder::swapIfBigEndian ((uint32) value);
|
||||
return write (&v, 4);
|
||||
}
|
||||
|
||||
bool OutputStream::writeIntBigEndian (int value)
|
||||
{
|
||||
auto v = ByteOrder::swapIfLittleEndian ((uint32) value);
|
||||
return write (&v, 4);
|
||||
}
|
||||
|
||||
bool OutputStream::writeCompressedInt (int value)
|
||||
{
|
||||
auto un = (value < 0) ? (unsigned int) -value
|
||||
: (unsigned int) value;
|
||||
|
||||
uint8 data[5];
|
||||
int num = 0;
|
||||
|
||||
while (un > 0)
|
||||
{
|
||||
data[++num] = (uint8) un;
|
||||
un >>= 8;
|
||||
}
|
||||
|
||||
data[0] = (uint8) num;
|
||||
|
||||
if (value < 0)
|
||||
data[0] |= 0x80;
|
||||
|
||||
return write (data, (size_t) num + 1);
|
||||
}
|
||||
|
||||
bool OutputStream::writeInt64 (int64 value)
|
||||
{
|
||||
auto v = ByteOrder::swapIfBigEndian ((uint64) value);
|
||||
return write (&v, 8);
|
||||
}
|
||||
|
||||
bool OutputStream::writeInt64BigEndian (int64 value)
|
||||
{
|
||||
auto v = ByteOrder::swapIfLittleEndian ((uint64) value);
|
||||
return write (&v, 8);
|
||||
}
|
||||
|
||||
bool OutputStream::writeFloat (float value)
|
||||
{
|
||||
union { int asInt; float asFloat; } n;
|
||||
n.asFloat = value;
|
||||
return writeInt (n.asInt);
|
||||
}
|
||||
|
||||
bool OutputStream::writeFloatBigEndian (float value)
|
||||
{
|
||||
union { int asInt; float asFloat; } n;
|
||||
n.asFloat = value;
|
||||
return writeIntBigEndian (n.asInt);
|
||||
}
|
||||
|
||||
bool OutputStream::writeDouble (double value)
|
||||
{
|
||||
union { int64 asInt; double asDouble; } n;
|
||||
n.asDouble = value;
|
||||
return writeInt64 (n.asInt);
|
||||
}
|
||||
|
||||
bool OutputStream::writeDoubleBigEndian (double value)
|
||||
{
|
||||
union { int64 asInt; double asDouble; } n;
|
||||
n.asDouble = value;
|
||||
return writeInt64BigEndian (n.asInt);
|
||||
}
|
||||
|
||||
bool OutputStream::writeString (const String& text)
|
||||
{
|
||||
auto numBytes = text.getNumBytesAsUTF8() + 1;
|
||||
|
||||
#if (JUCE_STRING_UTF_TYPE == 8)
|
||||
return write (text.toRawUTF8(), numBytes);
|
||||
#else
|
||||
// (This avoids using toUTF8() to prevent the memory bloat that it would leave behind
|
||||
// if lots of large, persistent strings were to be written to streams).
|
||||
HeapBlock<char> temp (numBytes);
|
||||
text.copyToUTF8 (temp, numBytes);
|
||||
return write (temp, numBytes);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool OutputStream::writeText (const String& text, bool asUTF16, bool writeUTF16ByteOrderMark, const char* lf)
|
||||
{
|
||||
bool replaceLineFeedWithUnix = lf != nullptr && lf[0] == '\n' && lf[1] == 0;
|
||||
bool replaceLineFeedWithWindows = lf != nullptr && lf[0] == '\r' && lf[1] == '\n' && lf[2] == 0;
|
||||
|
||||
// The line-feed passed in must be either nullptr, or "\n" or "\r\n"
|
||||
jassert (lf == nullptr || replaceLineFeedWithWindows || replaceLineFeedWithUnix);
|
||||
|
||||
if (asUTF16)
|
||||
{
|
||||
if (writeUTF16ByteOrderMark)
|
||||
write ("\x0ff\x0fe", 2);
|
||||
|
||||
auto src = text.getCharPointer();
|
||||
bool lastCharWasReturn = false;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
auto c = src.getAndAdvance();
|
||||
|
||||
if (c == 0)
|
||||
break;
|
||||
|
||||
if (replaceLineFeedWithWindows)
|
||||
{
|
||||
if (c == '\n' && ! lastCharWasReturn)
|
||||
writeShort ((short) '\r');
|
||||
|
||||
lastCharWasReturn = (c == L'\r');
|
||||
}
|
||||
else if (replaceLineFeedWithUnix && c == '\r')
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (! writeShort ((short) c))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const char* src = text.toRawUTF8();
|
||||
|
||||
if (replaceLineFeedWithWindows)
|
||||
{
|
||||
for (auto t = src;;)
|
||||
{
|
||||
if (*t == '\n')
|
||||
{
|
||||
if (t > src)
|
||||
if (! write (src, (size_t) (t - src)))
|
||||
return false;
|
||||
|
||||
if (! write ("\r\n", 2))
|
||||
return false;
|
||||
|
||||
src = t + 1;
|
||||
}
|
||||
else if (*t == '\r')
|
||||
{
|
||||
if (t[1] == '\n')
|
||||
++t;
|
||||
}
|
||||
else if (*t == 0)
|
||||
{
|
||||
if (t > src)
|
||||
if (! write (src, (size_t) (t - src)))
|
||||
return false;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
++t;
|
||||
}
|
||||
}
|
||||
else if (replaceLineFeedWithUnix)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
auto c = *src++;
|
||||
|
||||
if (c == 0)
|
||||
break;
|
||||
|
||||
if (c != '\r')
|
||||
if (! writeByte (c))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return write (src, text.getNumBytesAsUTF8());
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int64 OutputStream::writeFromInputStream (InputStream& source, int64 numBytesToWrite)
|
||||
{
|
||||
if (numBytesToWrite < 0)
|
||||
numBytesToWrite = std::numeric_limits<int64>::max();
|
||||
|
||||
int64 numWritten = 0;
|
||||
|
||||
while (numBytesToWrite > 0)
|
||||
{
|
||||
char buffer[8192];
|
||||
auto num = source.read (buffer, (int) jmin (numBytesToWrite, (int64) sizeof (buffer)));
|
||||
|
||||
if (num <= 0)
|
||||
break;
|
||||
|
||||
write (buffer, (size_t) num);
|
||||
|
||||
numBytesToWrite -= num;
|
||||
numWritten += num;
|
||||
}
|
||||
|
||||
return numWritten;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void OutputStream::setNewLineString (const String& newLineStringToUse)
|
||||
{
|
||||
newLineString = newLineStringToUse;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
template <typename IntegerType>
|
||||
static void writeIntToStream (OutputStream& stream, IntegerType number)
|
||||
{
|
||||
char buffer[NumberToStringConverters::charsNeededForInt];
|
||||
char* end = buffer + numElementsInArray (buffer);
|
||||
const char* start = NumberToStringConverters::numberToString (end, number);
|
||||
stream.write (start, (size_t) (end - start - 1));
|
||||
}
|
||||
|
||||
JUCE_API OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const int number)
|
||||
{
|
||||
writeIntToStream (stream, number);
|
||||
return stream;
|
||||
}
|
||||
|
||||
JUCE_API OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const int64 number)
|
||||
{
|
||||
writeIntToStream (stream, number);
|
||||
return stream;
|
||||
}
|
||||
|
||||
JUCE_API OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const double number)
|
||||
{
|
||||
return stream << String (number);
|
||||
}
|
||||
|
||||
JUCE_API OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const char character)
|
||||
{
|
||||
stream.writeByte (character);
|
||||
return stream;
|
||||
}
|
||||
|
||||
JUCE_API OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const char* const text)
|
||||
{
|
||||
stream.write (text, strlen (text));
|
||||
return stream;
|
||||
}
|
||||
|
||||
JUCE_API OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const MemoryBlock& data)
|
||||
{
|
||||
if (! data.isEmpty())
|
||||
stream.write (data.getData(), data.getSize());
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
JUCE_API OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const File& fileToRead)
|
||||
{
|
||||
FileInputStream in (fileToRead);
|
||||
|
||||
if (in.openedOk())
|
||||
return stream << in;
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
JUCE_API OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, InputStream& streamToRead)
|
||||
{
|
||||
stream.writeFromInputStream (streamToRead, -1);
|
||||
return stream;
|
||||
}
|
||||
|
||||
JUCE_API OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const NewLine&)
|
||||
{
|
||||
return stream << stream.getNewLineString();
|
||||
}
|
||||
|
||||
} // namespace juce
|
274
deps/juce/modules/juce_core/streams/juce_OutputStream.h
vendored
Normal file
274
deps/juce/modules/juce_core/streams/juce_OutputStream.h
vendored
Normal file
@ -0,0 +1,274 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
The code included in this file is provided 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.
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
The base class for streams that write data to some kind of destination.
|
||||
|
||||
Input and output streams are used throughout the library - subclasses can override
|
||||
some or all of the virtual functions to implement their behaviour.
|
||||
|
||||
@see InputStream, MemoryOutputStream, FileOutputStream
|
||||
|
||||
@tags{Core}
|
||||
*/
|
||||
class JUCE_API OutputStream
|
||||
{
|
||||
protected:
|
||||
//==============================================================================
|
||||
OutputStream();
|
||||
|
||||
public:
|
||||
/** Destructor.
|
||||
|
||||
Some subclasses might want to do things like call flush() during their
|
||||
destructors.
|
||||
*/
|
||||
virtual ~OutputStream();
|
||||
|
||||
//==============================================================================
|
||||
/** If the stream is using a buffer, this will ensure it gets written
|
||||
out to the destination. */
|
||||
virtual void flush() = 0;
|
||||
|
||||
/** Tries to move the stream's output position.
|
||||
|
||||
Not all streams will be able to seek to a new position - this will return
|
||||
false if it fails to work.
|
||||
|
||||
@see getPosition
|
||||
*/
|
||||
virtual bool setPosition (int64 newPosition) = 0;
|
||||
|
||||
/** Returns the stream's current position.
|
||||
|
||||
@see setPosition
|
||||
*/
|
||||
virtual int64 getPosition() = 0;
|
||||
|
||||
//==============================================================================
|
||||
/** Writes a block of data to the stream.
|
||||
|
||||
When creating a subclass of OutputStream, this is the only write method
|
||||
that needs to be overloaded - the base class has methods for writing other
|
||||
types of data which use this to do the work.
|
||||
|
||||
@param dataToWrite the target buffer to receive the data. This must not be null.
|
||||
@param numberOfBytes the number of bytes to write.
|
||||
@returns false if the write operation fails for some reason
|
||||
*/
|
||||
virtual bool write (const void* dataToWrite,
|
||||
size_t numberOfBytes) = 0;
|
||||
|
||||
//==============================================================================
|
||||
/** Writes a single byte to the stream.
|
||||
@returns false if the write operation fails for some reason
|
||||
@see InputStream::readByte
|
||||
*/
|
||||
virtual bool writeByte (char byte);
|
||||
|
||||
/** Writes a boolean to the stream as a single byte.
|
||||
This is encoded as a binary byte (not as text) with a value of 1 or 0.
|
||||
@returns false if the write operation fails for some reason
|
||||
@see InputStream::readBool
|
||||
*/
|
||||
virtual bool writeBool (bool boolValue);
|
||||
|
||||
/** Writes a 16-bit integer to the stream in a little-endian byte order.
|
||||
This will write two bytes to the stream: (value & 0xff), then (value >> 8).
|
||||
@returns false if the write operation fails for some reason
|
||||
@see InputStream::readShort
|
||||
*/
|
||||
virtual bool writeShort (short value);
|
||||
|
||||
/** Writes a 16-bit integer to the stream in a big-endian byte order.
|
||||
This will write two bytes to the stream: (value >> 8), then (value & 0xff).
|
||||
@returns false if the write operation fails for some reason
|
||||
@see InputStream::readShortBigEndian
|
||||
*/
|
||||
virtual bool writeShortBigEndian (short value);
|
||||
|
||||
/** Writes a 32-bit integer to the stream in a little-endian byte order.
|
||||
@returns false if the write operation fails for some reason
|
||||
@see InputStream::readInt
|
||||
*/
|
||||
virtual bool writeInt (int value);
|
||||
|
||||
/** Writes a 32-bit integer to the stream in a big-endian byte order.
|
||||
@returns false if the write operation fails for some reason
|
||||
@see InputStream::readIntBigEndian
|
||||
*/
|
||||
virtual bool writeIntBigEndian (int value);
|
||||
|
||||
/** Writes a 64-bit integer to the stream in a little-endian byte order.
|
||||
@returns false if the write operation fails for some reason
|
||||
@see InputStream::readInt64
|
||||
*/
|
||||
virtual bool writeInt64 (int64 value);
|
||||
|
||||
/** Writes a 64-bit integer to the stream in a big-endian byte order.
|
||||
@returns false if the write operation fails for some reason
|
||||
@see InputStream::readInt64BigEndian
|
||||
*/
|
||||
virtual bool writeInt64BigEndian (int64 value);
|
||||
|
||||
/** Writes a 32-bit floating point value to the stream in a binary format.
|
||||
The binary 32-bit encoding of the float is written as a little-endian int.
|
||||
@returns false if the write operation fails for some reason
|
||||
@see InputStream::readFloat
|
||||
*/
|
||||
virtual bool writeFloat (float value);
|
||||
|
||||
/** Writes a 32-bit floating point value to the stream in a binary format.
|
||||
The binary 32-bit encoding of the float is written as a big-endian int.
|
||||
@returns false if the write operation fails for some reason
|
||||
@see InputStream::readFloatBigEndian
|
||||
*/
|
||||
virtual bool writeFloatBigEndian (float value);
|
||||
|
||||
/** Writes a 64-bit floating point value to the stream in a binary format.
|
||||
The eight raw bytes of the double value are written out as a little-endian 64-bit int.
|
||||
@returns false if the write operation fails for some reason
|
||||
@see InputStream::readDouble
|
||||
*/
|
||||
virtual bool writeDouble (double value);
|
||||
|
||||
/** Writes a 64-bit floating point value to the stream in a binary format.
|
||||
The eight raw bytes of the double value are written out as a big-endian 64-bit int.
|
||||
@see InputStream::readDoubleBigEndian
|
||||
@returns false if the write operation fails for some reason
|
||||
*/
|
||||
virtual bool writeDoubleBigEndian (double value);
|
||||
|
||||
/** Writes a byte to the output stream a given number of times.
|
||||
@returns false if the write operation fails for some reason
|
||||
*/
|
||||
virtual bool writeRepeatedByte (uint8 byte, size_t numTimesToRepeat);
|
||||
|
||||
/** Writes a condensed binary encoding of a 32-bit integer.
|
||||
|
||||
If you're storing a lot of integers which are unlikely to have very large values,
|
||||
this can save a lot of space, because values under 0xff will only take up 2 bytes,
|
||||
under 0xffff only 3 bytes, etc.
|
||||
|
||||
The format used is: number of significant bytes + up to 4 bytes in little-endian order.
|
||||
|
||||
@returns false if the write operation fails for some reason
|
||||
@see InputStream::readCompressedInt
|
||||
*/
|
||||
virtual bool writeCompressedInt (int value);
|
||||
|
||||
/** Stores a string in the stream in a binary format.
|
||||
|
||||
This isn't the method to use if you're trying to append text to the end of a
|
||||
text-file! It's intended for storing a string so that it can be retrieved later
|
||||
by InputStream::readString().
|
||||
|
||||
It writes the string to the stream as UTF8, including the null termination character.
|
||||
|
||||
For appending text to a file, instead use writeText, or operator<<
|
||||
|
||||
@returns false if the write operation fails for some reason
|
||||
@see InputStream::readString, writeText, operator<<
|
||||
*/
|
||||
virtual bool writeString (const String& text);
|
||||
|
||||
/** Writes a string of text to the stream.
|
||||
|
||||
It can either write the text as UTF-8 or UTF-16, and can also add the UTF-16 byte-order-mark
|
||||
bytes (0xff, 0xfe) to indicate the endianness (these should only be used at the start
|
||||
of a file).
|
||||
|
||||
If lineEndings is nullptr, then line endings in the text won't be modified. If you
|
||||
pass "\\n" or "\\r\\n" then this function will replace any existing line feeds.
|
||||
|
||||
@returns false if the write operation fails for some reason
|
||||
*/
|
||||
virtual bool writeText (const String& text,
|
||||
bool asUTF16,
|
||||
bool writeUTF16ByteOrderMark,
|
||||
const char* lineEndings);
|
||||
|
||||
/** Reads data from an input stream and writes it to this stream.
|
||||
|
||||
@param source the stream to read from
|
||||
@param maxNumBytesToWrite the number of bytes to read from the stream (if this is
|
||||
less than zero, it will keep reading until the input
|
||||
is exhausted)
|
||||
@returns the number of bytes written
|
||||
*/
|
||||
virtual int64 writeFromInputStream (InputStream& source, int64 maxNumBytesToWrite);
|
||||
|
||||
//==============================================================================
|
||||
/** Sets the string to write to the stream when a new line is written.
|
||||
By default this will be set the value of NewLine::getDefault().
|
||||
*/
|
||||
void setNewLineString (const String& newLineString);
|
||||
|
||||
/** Returns the current new-line string that was set by setNewLineString(). */
|
||||
const String& getNewLineString() const noexcept { return newLineString; }
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
String newLineString;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OutputStream)
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
/** Writes a number to a stream as 8-bit characters in the default system encoding. */
|
||||
JUCE_API OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, int number);
|
||||
|
||||
/** Writes a number to a stream as 8-bit characters in the default system encoding. */
|
||||
JUCE_API OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, int64 number);
|
||||
|
||||
/** Writes a number to a stream as 8-bit characters in the default system encoding. */
|
||||
JUCE_API OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, double number);
|
||||
|
||||
/** Writes a character to a stream. */
|
||||
JUCE_API OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, char character);
|
||||
|
||||
/** Writes a null-terminated text string to a stream. */
|
||||
JUCE_API OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const char* text);
|
||||
|
||||
/** Writes a block of data from a MemoryBlock to a stream. */
|
||||
JUCE_API OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const MemoryBlock& data);
|
||||
|
||||
/** Writes the contents of a file to a stream. */
|
||||
JUCE_API OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const File& fileToRead);
|
||||
|
||||
/** Writes the complete contents of an input stream to an output stream. */
|
||||
JUCE_API OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, InputStream& streamToRead);
|
||||
|
||||
/** Writes a new-line to a stream.
|
||||
You can use the predefined symbol 'newLine' to invoke this, e.g.
|
||||
@code
|
||||
myOutputStream << "Hello World" << newLine << newLine;
|
||||
@endcode
|
||||
@see OutputStream::setNewLineString
|
||||
*/
|
||||
JUCE_API OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const NewLine&);
|
||||
|
||||
} // namespace juce
|
160
deps/juce/modules/juce_core/streams/juce_SubregionStream.cpp
vendored
Normal file
160
deps/juce/modules/juce_core/streams/juce_SubregionStream.cpp
vendored
Normal file
@ -0,0 +1,160 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
The code included in this file is provided 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.
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
SubregionStream::SubregionStream (InputStream* sourceStream,
|
||||
int64 start, int64 length,
|
||||
bool deleteSourceWhenDestroyed)
|
||||
: source (sourceStream, deleteSourceWhenDestroyed),
|
||||
startPositionInSourceStream (start),
|
||||
lengthOfSourceStream (length)
|
||||
{
|
||||
SubregionStream::setPosition (0);
|
||||
}
|
||||
|
||||
SubregionStream::~SubregionStream()
|
||||
{
|
||||
}
|
||||
|
||||
int64 SubregionStream::getTotalLength()
|
||||
{
|
||||
auto srcLen = source->getTotalLength() - startPositionInSourceStream;
|
||||
|
||||
return lengthOfSourceStream >= 0 ? jmin (lengthOfSourceStream, srcLen)
|
||||
: srcLen;
|
||||
}
|
||||
|
||||
int64 SubregionStream::getPosition()
|
||||
{
|
||||
return source->getPosition() - startPositionInSourceStream;
|
||||
}
|
||||
|
||||
bool SubregionStream::setPosition (int64 newPosition)
|
||||
{
|
||||
return source->setPosition (jmax ((int64) 0, newPosition + startPositionInSourceStream));
|
||||
}
|
||||
|
||||
int SubregionStream::read (void* destBuffer, int maxBytesToRead)
|
||||
{
|
||||
jassert (destBuffer != nullptr && maxBytesToRead >= 0);
|
||||
|
||||
if (lengthOfSourceStream < 0)
|
||||
return source->read (destBuffer, maxBytesToRead);
|
||||
|
||||
maxBytesToRead = (int) jmin ((int64) maxBytesToRead, lengthOfSourceStream - getPosition());
|
||||
|
||||
if (maxBytesToRead <= 0)
|
||||
return 0;
|
||||
|
||||
return source->read (destBuffer, maxBytesToRead);
|
||||
}
|
||||
|
||||
bool SubregionStream::isExhausted()
|
||||
{
|
||||
if (lengthOfSourceStream >= 0 && getPosition() >= lengthOfSourceStream)
|
||||
return true;
|
||||
|
||||
return source->isExhausted();
|
||||
}
|
||||
|
||||
|
||||
//==============================================================================
|
||||
//==============================================================================
|
||||
#if JUCE_UNIT_TESTS
|
||||
|
||||
struct SubregionInputStreamTests : public UnitTest
|
||||
{
|
||||
SubregionInputStreamTests()
|
||||
: UnitTest ("SubregionInputStream", UnitTestCategories::streams)
|
||||
{}
|
||||
|
||||
void runTest() override
|
||||
{
|
||||
const MemoryBlock data ("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz", 52);
|
||||
MemoryInputStream mi (data, true);
|
||||
|
||||
const int offset = getRandom().nextInt ((int) data.getSize());
|
||||
const size_t subregionSize = data.getSize() - (size_t) offset;
|
||||
|
||||
SubregionStream stream (&mi, offset, (int) subregionSize, false);
|
||||
|
||||
beginTest ("Read");
|
||||
|
||||
expectEquals (stream.getPosition(), (int64) 0);
|
||||
expectEquals (stream.getTotalLength(), (int64) subregionSize);
|
||||
expectEquals (stream.getNumBytesRemaining(), stream.getTotalLength());
|
||||
expect (! stream.isExhausted());
|
||||
|
||||
size_t numBytesRead = 0;
|
||||
MemoryBlock readBuffer (subregionSize);
|
||||
|
||||
while (numBytesRead < subregionSize)
|
||||
{
|
||||
numBytesRead += (size_t) stream.read (&readBuffer[numBytesRead], 3);
|
||||
|
||||
expectEquals (stream.getPosition(), (int64) numBytesRead);
|
||||
expectEquals (stream.getNumBytesRemaining(), (int64) (subregionSize - numBytesRead));
|
||||
expect (stream.isExhausted() == (numBytesRead == subregionSize));
|
||||
}
|
||||
|
||||
expectEquals (stream.getPosition(), (int64) subregionSize);
|
||||
expectEquals (stream.getNumBytesRemaining(), (int64) 0);
|
||||
expect (stream.isExhausted());
|
||||
|
||||
const MemoryBlock memoryBlockToCheck (data.begin() + (size_t) offset, data.getSize() - (size_t) offset);
|
||||
expect (readBuffer == memoryBlockToCheck);
|
||||
|
||||
beginTest ("Skip");
|
||||
|
||||
stream.setPosition (0);
|
||||
expectEquals (stream.getPosition(), (int64) 0);
|
||||
expectEquals (stream.getTotalLength(), (int64) subregionSize);
|
||||
expectEquals (stream.getNumBytesRemaining(), stream.getTotalLength());
|
||||
expect (! stream.isExhausted());
|
||||
|
||||
numBytesRead = 0;
|
||||
const int64 numBytesToSkip = 5;
|
||||
|
||||
while (numBytesRead < subregionSize)
|
||||
{
|
||||
stream.skipNextBytes (numBytesToSkip);
|
||||
numBytesRead += numBytesToSkip;
|
||||
numBytesRead = std::min (numBytesRead, subregionSize);
|
||||
|
||||
expectEquals (stream.getPosition(), (int64) numBytesRead);
|
||||
expectEquals (stream.getNumBytesRemaining(), (int64) (subregionSize - numBytesRead));
|
||||
expect (stream.isExhausted() == (numBytesRead == subregionSize));
|
||||
}
|
||||
|
||||
expectEquals (stream.getPosition(), (int64) subregionSize);
|
||||
expectEquals (stream.getNumBytesRemaining(), (int64) 0);
|
||||
expect (stream.isExhausted());
|
||||
}
|
||||
};
|
||||
|
||||
static SubregionInputStreamTests subregionInputStreamTests;
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace juce
|
83
deps/juce/modules/juce_core/streams/juce_SubregionStream.h
vendored
Normal file
83
deps/juce/modules/juce_core/streams/juce_SubregionStream.h
vendored
Normal file
@ -0,0 +1,83 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
The code included in this file is provided 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.
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
/** Wraps another input stream, and reads from a specific part of it.
|
||||
|
||||
This lets you take a subsection of a stream and present it as an entire
|
||||
stream in its own right.
|
||||
|
||||
@tags{Core}
|
||||
*/
|
||||
class JUCE_API SubregionStream : public InputStream
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Creates a SubregionStream from an input source.
|
||||
|
||||
@param sourceStream the source stream to read from
|
||||
@param startPositionInSourceStream this is the position in the source stream that
|
||||
corresponds to position 0 in this stream
|
||||
@param lengthOfSourceStream this specifies the maximum number of bytes
|
||||
from the source stream that will be passed through
|
||||
by this stream. When the position of this stream
|
||||
exceeds lengthOfSourceStream, it will cause an end-of-stream.
|
||||
If the length passed in here is greater than the length
|
||||
of the source stream (as returned by getTotalLength()),
|
||||
then the smaller value will be used.
|
||||
Passing a negative value for this parameter means it
|
||||
will keep reading until the source's end-of-stream.
|
||||
@param deleteSourceWhenDestroyed whether the sourceStream that is passed in should be
|
||||
deleted by this object when it is itself deleted.
|
||||
*/
|
||||
SubregionStream (InputStream* sourceStream,
|
||||
int64 startPositionInSourceStream,
|
||||
int64 lengthOfSourceStream,
|
||||
bool deleteSourceWhenDestroyed);
|
||||
|
||||
/** Destructor.
|
||||
|
||||
This may also delete the source stream, if that option was chosen when the
|
||||
buffered stream was created.
|
||||
*/
|
||||
~SubregionStream() override;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
int64 getTotalLength() override;
|
||||
int64 getPosition() override;
|
||||
bool setPosition (int64 newPosition) override;
|
||||
int read (void* destBuffer, int maxBytesToRead) override;
|
||||
bool isExhausted() override;
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
OptionalScopedPointer<InputStream> source;
|
||||
const int64 startPositionInSourceStream, lengthOfSourceStream;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SubregionStream)
|
||||
};
|
||||
|
||||
} // namespace juce
|
62
deps/juce/modules/juce_core/streams/juce_URLInputSource.cpp
vendored
Normal file
62
deps/juce/modules/juce_core/streams/juce_URLInputSource.cpp
vendored
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
The code included in this file is provided 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.
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
URLInputSource::URLInputSource (const URL& url)
|
||||
: u (url)
|
||||
{
|
||||
}
|
||||
|
||||
URLInputSource::URLInputSource (URL&& url)
|
||||
: u (std::move (url))
|
||||
{
|
||||
}
|
||||
|
||||
URLInputSource::~URLInputSource()
|
||||
{
|
||||
}
|
||||
|
||||
InputStream* URLInputSource::createInputStream()
|
||||
{
|
||||
return u.createInputStream (URL::InputStreamOptions (URL::ParameterHandling::inAddress)).release();
|
||||
}
|
||||
|
||||
InputStream* URLInputSource::createInputStreamFor (const String& relatedItemPath)
|
||||
{
|
||||
auto sub = u.getSubPath();
|
||||
auto parent = sub.containsChar (L'/') ? sub.upToLastOccurrenceOf ("/", false, false)
|
||||
: String ();
|
||||
|
||||
return u.withNewSubPath (parent)
|
||||
.getChildURL (relatedItemPath)
|
||||
.createInputStream (URL::InputStreamOptions (URL::ParameterHandling::inAddress))
|
||||
.release();
|
||||
}
|
||||
|
||||
int64 URLInputSource::hashCode() const
|
||||
{
|
||||
return u.toString (true).hashCode64();
|
||||
}
|
||||
|
||||
} // namespace juce
|
61
deps/juce/modules/juce_core/streams/juce_URLInputSource.h
vendored
Normal file
61
deps/juce/modules/juce_core/streams/juce_URLInputSource.h
vendored
Normal file
@ -0,0 +1,61 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
The code included in this file is provided 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.
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
A type of InputSource that represents a URL.
|
||||
|
||||
@see InputSource
|
||||
|
||||
@tags{Core}
|
||||
*/
|
||||
class JUCE_API URLInputSource : public InputSource
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Creates a URLInputSource for a url. */
|
||||
URLInputSource (const URL& url);
|
||||
|
||||
/** Move constructor which will move the URL into the InputSource.
|
||||
|
||||
This is useful when the url carries any security credentials.
|
||||
*/
|
||||
URLInputSource (URL&& url);
|
||||
|
||||
/** Destructor. */
|
||||
~URLInputSource() override;
|
||||
|
||||
InputStream* createInputStream() override;
|
||||
InputStream* createInputStreamFor (const String& relatedItemPath) override;
|
||||
int64 hashCode() const override;
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
const URL u;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (URLInputSource)
|
||||
};
|
||||
|
||||
}
|
Reference in New Issue
Block a user