OpenShot Audio Library | OpenShotAudio  0.3.0
juce_MemoryOutputStream.cpp
1 /*
2  ==============================================================================
3 
4  This file is part of the JUCE library.
5  Copyright (c) 2017 - ROLI Ltd.
6 
7  JUCE is an open source library subject to commercial or open-source
8  licensing.
9 
10  The code included in this file is provided under the terms of the ISC license
11  http://www.isc.org/downloads/software-support-policy/isc-license. Permission
12  To use, copy, modify, and/or distribute this software for any purpose with or
13  without fee is hereby granted provided that the above copyright notice and
14  this permission notice appear in all copies.
15 
16  JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
17  EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
18  DISCLAIMED.
19 
20  ==============================================================================
21 */
22 
23 namespace juce
24 {
25 
26 MemoryOutputStream::MemoryOutputStream (const size_t initialSize)
27  : blockToUse (&internalBlock)
28 {
29  internalBlock.setSize (initialSize, false);
30 }
31 
33  const bool appendToExistingBlockContent)
34  : blockToUse (&memoryBlockToWriteTo)
35 {
36  if (appendToExistingBlockContent)
37  position = size = memoryBlockToWriteTo.getSize();
38 }
39 
40 MemoryOutputStream::MemoryOutputStream (void* destBuffer, size_t destBufferSize)
41  : externalData (destBuffer), availableSize (destBufferSize)
42 {
43  jassert (externalData != nullptr); // This must be a valid pointer.
44 }
45 
47 {
48  trimExternalBlockSize();
49 }
50 
52 {
53  trimExternalBlockSize();
54 }
55 
56 void MemoryOutputStream::trimExternalBlockSize()
57 {
58  if (blockToUse != &internalBlock && blockToUse != nullptr)
59  blockToUse->setSize (size, false);
60 }
61 
62 void MemoryOutputStream::preallocate (const size_t bytesToPreallocate)
63 {
64  if (blockToUse != nullptr)
65  blockToUse->ensureSize (bytesToPreallocate + 1);
66 }
67 
69 {
70  position = 0;
71  size = 0;
72 }
73 
74 char* MemoryOutputStream::prepareToWrite (size_t numBytes)
75 {
76  jassert ((ssize_t) numBytes >= 0);
77  auto storageNeeded = position + numBytes;
78 
79  char* data;
80 
81  if (blockToUse != nullptr)
82  {
83  if (storageNeeded >= blockToUse->getSize())
84  blockToUse->ensureSize ((storageNeeded + jmin (storageNeeded / 2, (size_t) (1024 * 1024)) + 32) & ~31u);
85 
86  data = static_cast<char*> (blockToUse->getData());
87  }
88  else
89  {
90  if (storageNeeded > availableSize)
91  return nullptr;
92 
93  data = static_cast<char*> (externalData);
94  }
95 
96  auto* writePointer = data + position;
97  position += numBytes;
98  size = jmax (size, position);
99  return writePointer;
100 }
101 
102 bool MemoryOutputStream::write (const void* const buffer, size_t howMany)
103 {
104  if (howMany == 0)
105  return true;
106 
107  jassert (buffer != nullptr);
108 
109  if (auto* dest = prepareToWrite (howMany))
110  {
111  memcpy (dest, buffer, howMany);
112  return true;
113  }
114 
115  return false;
116 }
117 
118 bool MemoryOutputStream::writeRepeatedByte (uint8 byte, size_t howMany)
119 {
120  if (howMany == 0)
121  return true;
122 
123  if (auto* dest = prepareToWrite (howMany))
124  {
125  memset (dest, byte, howMany);
126  return true;
127  }
128 
129  return false;
130 }
131 
133 {
134  if (auto* dest = prepareToWrite (CharPointer_UTF8::getBytesRequiredFor (c)))
135  {
136  CharPointer_UTF8 (dest).write (c);
137  return true;
138  }
139 
140  return false;
141 }
142 
144 {
145  return MemoryBlock (getData(), getDataSize());
146 }
147 
148 const void* MemoryOutputStream::getData() const noexcept
149 {
150  if (blockToUse == nullptr)
151  return externalData;
152 
153  if (blockToUse->getSize() > size)
154  static_cast<char*> (blockToUse->getData()) [size] = 0;
155 
156  return blockToUse->getData();
157 }
158 
159 bool MemoryOutputStream::setPosition (int64 newPosition)
160 {
161  if (newPosition <= (int64) size)
162  {
163  // ok to seek backwards
164  position = jlimit ((size_t) 0, size, (size_t) newPosition);
165  return true;
166  }
167 
168  // can't move beyond the end of the stream..
169  return false;
170 }
171 
172 int64 MemoryOutputStream::writeFromInputStream (InputStream& source, int64 maxNumBytesToWrite)
173 {
174  // before writing from an input, see if we can preallocate to make it more efficient..
175  int64 availableData = source.getTotalLength() - source.getPosition();
176 
177  if (availableData > 0)
178  {
179  if (maxNumBytesToWrite > availableData || maxNumBytesToWrite < 0)
180  maxNumBytesToWrite = availableData;
181 
182  if (blockToUse != nullptr)
183  preallocate (blockToUse->getSize() + (size_t) maxNumBytesToWrite);
184  }
185 
186  return OutputStream::writeFromInputStream (source, maxNumBytesToWrite);
187 }
188 
190 {
191  auto* d = static_cast<const char*> (getData());
192  return String (CharPointer_UTF8 (d), CharPointer_UTF8 (d + getDataSize()));
193 }
194 
196 {
198 }
199 
200 OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const MemoryOutputStream& streamToRead)
201 {
202  auto dataSize = streamToRead.getDataSize();
203 
204  if (dataSize > 0)
205  stream.write (streamToRead.getData(), dataSize);
206 
207  return stream;
208 }
209 
210 } // namespace juce
static size_t getBytesRequiredFor(const juce_wchar charToWrite) noexcept
size_t getSize() const noexcept
void preallocate(size_t bytesToPreallocate)
virtual int64 getTotalLength()=0
virtual bool write(const void *dataToWrite, size_t numberOfBytes)=0
void ensureSize(const size_t minimumSize, bool initialiseNewSpaceToZero=false)
int64 writeFromInputStream(InputStream &, int64 maxNumBytesToWrite) override
static String createStringFromData(const void *data, int size)
virtual int64 getPosition()=0
const void * getData() const noexcept
void * getData() noexcept
bool writeRepeatedByte(uint8 byte, size_t numTimesToRepeat) override
bool write(const void *, size_t) override
size_t getDataSize() const noexcept
MemoryOutputStream(size_t initialSize=256)
virtual int64 writeFromInputStream(InputStream &source, int64 maxNumBytesToWrite)
bool appendUTF8Char(juce_wchar character)
void setSize(const size_t newSize, bool initialiseNewSpaceToZero=false)
void write(const juce_wchar charToWrite) noexcept