/*
  ==============================================================================

   This file is part of the JUCE library - "Jules' Utility Class Extensions"
   Copyright 2004-6 by Raw Material Software ltd.

  ------------------------------------------------------------------------------

   JUCE can be redistributed and/or modified under the terms of the
   GNU General Public License, as published by the Free Software Foundation;
   either version 2 of the License, or (at your option) any later version.

   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.

   You should have received a copy of the GNU General Public License
   along with JUCE; if not, visit www.gnu.org/licenses or write to the
   Free Software Foundation, Inc., 59 Temple Place, Suite 330, 
   Boston, MA 02111-1307 USA

  ------------------------------------------------------------------------------

   If you'd like to release a closed-source product which uses JUCE, commercial
   licenses are also available: visit www.rawmaterialsoftware.com/juce for
   more information.

  ==============================================================================
*/

#ifndef __JUCE_OUTPUTSTREAM_JUCEHEADER__
#define __JUCE_OUTPUTSTREAM_JUCEHEADER__

#include "../text/juce_String.h"
#include "juce_InputStream.h"


//==============================================================================
/**
    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
*/
class JUCE_API  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.

        @returns false if the write operation fails for some reason
    */
    virtual bool write (const void* dataToWrite,
                        int howManyBytes) = 0;

    //==============================================================================
    /** Writes a single byte to the stream.

        @see InputStream::readByte
    */
    virtual void writeByte (char byte);

    /** Writes a boolean to the stream.

        This is encoded as a byte - either 1 or 0.

        @see InputStream::readBool
    */
    virtual void 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).

        @see InputStream::readShort
    */
    virtual void 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).

        @see InputStream::readShortBigEndian
    */
    virtual void writeShortBigEndian (short value);

    /** Writes a 32-bit integer to the stream in a little-endian byte order.

        @see InputStream::readInt
    */
    virtual void writeInt (int value);

    /** Writes a 32-bit integer to the stream in a big-endian byte order.

        @see InputStream::readIntBigEndian
    */
    virtual void writeIntBigEndian (int value);

    /** Writes a 64-bit integer to the stream in a little-endian byte order.

        @see InputStream::readInt64
    */
    virtual void writeInt64 (int64 value);

    /** Writes a 64-bit integer to the stream in a big-endian byte order.

        @see InputStream::readInt64BigEndian
    */
    virtual void writeInt64BigEndian (int64 value);

    /** Writes a 32-bit floating point value to the stream.

        The binary 32-bit encoding of the float is written as a little-endian int.

        @see InputStream::readFloat
    */
    virtual void writeFloat (float value);

    /** Writes a 64-bit floating point value to the stream.

        The eight raw bytes of the double value are written out as a little-endian 64-bit int.

        @see InputStream::readDouble
    */
    virtual void writeDouble (double value);

    /** Writes a condensed 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.

        @see InputStream::readCompressedInt
    */
    virtual void writeCompressedInt (int value);

    /** Stores a string in the stream.

        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 for later retrieval
        by InputStream::readString.

        For appending text to a file, instead use writeText, printf, or operator<<

        @see InputStream::readString, writeText, printf, operator<<
    */
    virtual void writeString (const String& text);

    /** Writes a string of text to the stream.

        It can either write it as ascii or unicode, and can also add unicode
        header bytes (0xff, 0xfe) to indicate the endianness (this should only
        be done at the start of a file).

        The method also replaces '\\n' characters in the text with '\\r\\n'.
    */
    virtual void writeText (const String& text,
                            const bool asUnicode,
                            const bool writeUnicodeHeaderBytes);

    /** Writes a string of ascii text to the stream.

        @see writeText
    */
    virtual void printf (const char* format, ...);

    /** 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)
    */
    virtual int writeFromInputStream (InputStream& source,
                                      int maxNumBytesToWrite);

    //==============================================================================
    /** Writes a number to the stream as ascii text. */
    virtual OutputStream& operator<< (const int number);

    /** Writes a number to the stream as ascii text. */
    virtual OutputStream& operator<< (const double number);

    /** Writes an ascii character to the stream. */
    virtual OutputStream& operator<< (const char asciiCharacter);

    /** Writes an ascii text string to the stream. */
    virtual OutputStream& operator<< (const char* const text);

    /** Writes a unicode text string to the stream. */
    virtual OutputStream& operator<< (const juce_wchar* const text);

    /** Writes a text string to the stream as ascii. */
    virtual OutputStream& operator<< (const String& text);


    //==============================================================================
    juce_UseDebuggingNewOperator


protected:
    //==============================================================================
    OutputStream() throw()  {}
};

#endif   // __JUCE_OUTPUTSTREAM_JUCEHEADER__
