Cleanup
[carla.git] / source / modules / water / streams / MemoryOutputStream.cpp
blobee1eb046e81247a9e63d09ca982c434d47937aa8
1 /*
2 ==============================================================================
4 This file is part of the Water library.
5 Copyright (c) 2016 ROLI Ltd.
6 Copyright (C) 2017 Filipe Coelho <falktx@falktx.com>
8 Permission is granted to use this software under the terms of the ISC license
9 http://www.isc.org/downloads/software-support-policy/isc-license/
11 Permission to use, copy, modify, and/or distribute this software for any
12 purpose with or without fee is hereby granted, provided that the above
13 copyright notice and this permission notice appear in all copies.
15 THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD
16 TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT,
18 OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
19 USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
20 TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
21 OF THIS SOFTWARE.
23 ==============================================================================
26 #include "MemoryOutputStream.h"
27 #include "InputStream.h"
29 namespace water {
31 MemoryOutputStream::MemoryOutputStream (const size_t initialSize)
32 : internalBlock(), blockToUse (internalBlock),
33 position (0), size (0),
34 usingInternalBlock (true)
36 internalBlock.setSize (initialSize, false);
39 MemoryOutputStream::MemoryOutputStream (MemoryBlock& memoryBlockToWriteTo,
40 const bool appendToExistingBlockContent)
41 : internalBlock(), blockToUse (memoryBlockToWriteTo),
42 position (0), size (0),
43 usingInternalBlock (false)
45 if (appendToExistingBlockContent)
46 position = size = memoryBlockToWriteTo.getSize();
49 MemoryOutputStream::~MemoryOutputStream()
51 trimExternalBlockSize();
54 void MemoryOutputStream::flush()
56 trimExternalBlockSize();
59 void MemoryOutputStream::trimExternalBlockSize()
61 if (! usingInternalBlock)
62 blockToUse.setSize (size, false);
65 void MemoryOutputStream::preallocate (const size_t bytesToPreallocate)
67 blockToUse.ensureSize (bytesToPreallocate + 1);
70 void MemoryOutputStream::reset() noexcept
72 position = 0;
73 size = 0;
76 char* MemoryOutputStream::prepareToWrite (size_t numBytes)
78 CARLA_SAFE_ASSERT_RETURN ((ssize_t) numBytes >= 0, nullptr);
80 const size_t storageNeeded = position + numBytes;
82 if (storageNeeded >= blockToUse.getSize())
83 blockToUse.ensureSize ((storageNeeded + jmin (storageNeeded / 2, (size_t) (1024 * 1024)) + 32) & ~31u);
85 char* const data = static_cast<char*> (blockToUse.getData());
86 char* const writePointer = data + position;
87 position += numBytes;
88 size = jmax (size, position);
89 return writePointer;
92 bool MemoryOutputStream::write (const void* const buffer, size_t howMany)
94 CARLA_SAFE_ASSERT_RETURN (buffer != nullptr, false);
96 if (howMany == 0)
97 return true;
99 if (char* const dest = prepareToWrite (howMany))
101 std::memcpy (dest, buffer, howMany);
102 return true;
105 return false;
108 bool MemoryOutputStream::writeRepeatedByte (uint8 byte, size_t howMany)
110 if (howMany == 0)
111 return true;
113 if (char* dest = prepareToWrite (howMany))
115 memset (dest, byte, howMany);
116 return true;
119 return false;
122 bool MemoryOutputStream::appendUTF8Char (water_uchar c)
124 if (char* dest = prepareToWrite (CharPointer_UTF8::getBytesRequiredFor (c)))
126 CharPointer_UTF8 (dest).write (c);
127 return true;
130 return false;
133 MemoryBlock MemoryOutputStream::getMemoryBlock() const
135 return MemoryBlock (getData(), getDataSize());
138 const void* MemoryOutputStream::getData() const noexcept
140 if (blockToUse.getSize() > size)
141 static_cast<char*> (blockToUse.getData()) [size] = 0;
143 return blockToUse.getData();
146 void* MemoryOutputStream::getDataAndRelease() noexcept
148 if (blockToUse.getSize() > size)
149 static_cast<char*> (blockToUse.getData()) [size] = 0;
151 return blockToUse.release();
154 bool MemoryOutputStream::setPosition (int64 newPosition)
156 if (newPosition <= (int64) size)
158 // ok to seek backwards
159 position = jlimit ((size_t) 0, size, (size_t) newPosition);
160 return true;
163 // can't move beyond the end of the stream..
164 return false;
167 int64 MemoryOutputStream::writeFromInputStream (InputStream& source, int64 maxNumBytesToWrite)
169 // before writing from an input, see if we can preallocate to make it more efficient..
170 int64 availableData = source.getTotalLength() - source.getPosition();
172 if (availableData > 0)
174 if (maxNumBytesToWrite > availableData || maxNumBytesToWrite < 0)
175 maxNumBytesToWrite = availableData;
177 preallocate (blockToUse.getSize() + (size_t) maxNumBytesToWrite);
180 return OutputStream::writeFromInputStream (source, maxNumBytesToWrite);
183 String MemoryOutputStream::toUTF8() const
185 const char* const d = static_cast<const char*> (getData());
186 return String (CharPointer_UTF8 (d), CharPointer_UTF8 (d + getDataSize()));
189 String MemoryOutputStream::toString() const
191 return String::createStringFromData (getData(), (int) getDataSize());
194 OutputStream& operator<< (OutputStream& stream, const MemoryOutputStream& streamToRead)
196 const size_t dataSize = streamToRead.getDataSize();
198 if (dataSize > 0)
199 stream.write (streamToRead.getData(), dataSize);
201 return stream;