1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-14 00:14:18 +00:00
JUCE/src/io/streams/juce_OutputStream.cpp

330 lines
8 KiB
C++

/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-9 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
#include "../../core/juce_StandardHeader.h"
BEGIN_JUCE_NAMESPACE
#include "juce_OutputStream.h"
#include "../../threads/juce_CriticalSection.h"
#include "../../containers/juce_VoidArray.h"
//==============================================================================
#if JUCE_DEBUG
static CriticalSection activeStreamLock;
static VoidArray activeStreams;
void juce_CheckForDanglingStreams()
{
/*
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);
};
#endif
//==============================================================================
OutputStream::OutputStream() throw()
{
#if JUCE_DEBUG
activeStreamLock.enter();
activeStreams.add (this);
activeStreamLock.exit();
#endif
}
OutputStream::~OutputStream()
{
#if JUCE_DEBUG
activeStreamLock.enter();
activeStreams.removeValue (this);
activeStreamLock.exit();
#endif
}
//==============================================================================
void OutputStream::writeBool (bool b)
{
writeByte ((b) ? (char) 1
: (char) 0);
}
void OutputStream::writeByte (char byte)
{
write (&byte, 1);
}
void OutputStream::writeShort (short value)
{
const unsigned short v = ByteOrder::swapIfBigEndian ((unsigned short) value);
write (&v, 2);
}
void OutputStream::writeShortBigEndian (short value)
{
const unsigned short v = ByteOrder::swapIfLittleEndian ((unsigned short) value);
write (&v, 2);
}
void OutputStream::writeInt (int value)
{
const unsigned int v = ByteOrder::swapIfBigEndian ((unsigned int) value);
write (&v, 4);
}
void OutputStream::writeIntBigEndian (int value)
{
const unsigned int v = ByteOrder::swapIfLittleEndian ((unsigned int) value);
write (&v, 4);
}
void OutputStream::writeCompressedInt (int value)
{
unsigned int 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;
write (data, num + 1);
}
void OutputStream::writeInt64 (int64 value)
{
const uint64 v = ByteOrder::swapIfBigEndian ((uint64) value);
write (&v, 8);
}
void OutputStream::writeInt64BigEndian (int64 value)
{
const uint64 v = ByteOrder::swapIfLittleEndian ((uint64) value);
write (&v, 8);
}
void OutputStream::writeFloat (float value)
{
union { int asInt; float asFloat; } n;
n.asFloat = value;
writeInt (n.asInt);
}
void OutputStream::writeFloatBigEndian (float value)
{
union { int asInt; float asFloat; } n;
n.asFloat = value;
writeIntBigEndian (n.asInt);
}
void OutputStream::writeDouble (double value)
{
union { int64 asInt; double asDouble; } n;
n.asDouble = value;
writeInt64 (n.asInt);
}
void OutputStream::writeDoubleBigEndian (double value)
{
union { int64 asInt; double asDouble; } n;
n.asDouble = value;
writeInt64BigEndian (n.asInt);
}
void OutputStream::writeString (const String& text)
{
const int numBytes = text.copyToUTF8 (0);
HeapBlock <uint8> temp (numBytes);
text.copyToUTF8 (temp);
write (temp, numBytes); // (numBytes includes the terminating null).
}
void OutputStream::printf (const char* pf, ...)
{
unsigned int bufSize = 256;
HeapBlock <char> buf (bufSize);
for (;;)
{
va_list list;
va_start (list, pf);
const int num = CharacterFunctions::vprintf (buf, bufSize, pf, list);
va_end (list);
if (num > 0)
{
write (buf, num);
break;
}
else if (num == 0)
{
break;
}
bufSize += 256;
buf.malloc (bufSize);
}
}
OutputStream& OutputStream::operator<< (const int number)
{
const String s (number);
write ((const char*) s, s.length());
return *this;
}
OutputStream& OutputStream::operator<< (const double number)
{
const String s (number);
write ((const char*) s, s.length());
return *this;
}
OutputStream& OutputStream::operator<< (const char character)
{
writeByte (character);
return *this;
}
OutputStream& OutputStream::operator<< (const char* const text)
{
write (text, (int) strlen (text));
return *this;
}
OutputStream& OutputStream::operator<< (const juce_wchar* const text)
{
const String s (text);
write ((const char*) s, s.length());
return *this;
}
OutputStream& OutputStream::operator<< (const String& text)
{
write ((const char*) text,
text.length());
return *this;
}
void OutputStream::writeText (const String& text,
const bool asUnicode,
const bool writeUnicodeHeaderBytes)
{
if (asUnicode)
{
if (writeUnicodeHeaderBytes)
write ("\x0ff\x0fe", 2);
const juce_wchar* src = (const juce_wchar*) text;
bool lastCharWasReturn = false;
while (*src != 0)
{
if (*src == L'\n' && ! lastCharWasReturn)
writeShort ((short) L'\r');
lastCharWasReturn = (*src == L'\r');
writeShort ((short) *src++);
}
}
else
{
const char* src = (const char*) text;
const char* t = src;
for (;;)
{
if (*t == '\n')
{
if (t > src)
write (src, (int) (t - src));
write ("\r\n", 2);
src = t + 1;
}
else if (*t == '\r')
{
if (t[1] == '\n')
++t;
}
else if (*t == 0)
{
if (t > src)
write (src, (int) (t - src));
break;
}
++t;
}
}
}
int OutputStream::writeFromInputStream (InputStream& source,
int numBytesToWrite)
{
if (numBytesToWrite < 0)
numBytesToWrite = 0x7fffffff;
int numWritten = 0;
while (numBytesToWrite > 0 && ! source.isExhausted())
{
char buffer [8192];
const int num = source.read (buffer, jmin (numBytesToWrite, sizeof (buffer)));
if (num == 0)
break;
write (buffer, num);
numBytesToWrite -= num;
numWritten += num;
}
return numWritten;
}
END_JUCE_NAMESPACE