/**
 * @file llbufferstream.h
 * @author Phoenix
 * @date 2005-10-10
 * @brief Classes to treat an LLBufferArray as a c++ iostream.
 *
 * $LicenseInfo:firstyear=2005&license=viewerlgpl$
 * Second Life Viewer Source Code
 * Copyright (C) 2010, Linden Research, Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation;
 * version 2.1 of the License only.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 * $/LicenseInfo$
 */

#ifndef LL_LLBUFFERSTREAM_H
#define LL_LLBUFFERSTREAM_H

#include <iosfwd>
#include <iostream>
#include "llbuffer.h"

/**
 * @class LLBufferStreamBuf
 * @brief This implements the buffer wrapper for an istream
 *
 * The buffer array passed in is not owned by the stream buf object.
 */
class LLBufferStreamBuf : public std::streambuf
{
public:
    LLBufferStreamBuf(
        const LLChannelDescriptors& channels,
        LLBufferArray* buffer);
    virtual ~LLBufferStreamBuf();

protected:
#if( LL_WINDOWS || __GNUC__ > 2 )
    typedef std::streambuf::pos_type pos_type;
    typedef std::streambuf::off_type off_type;
#endif

    /* @name streambuf vrtual implementations
     */
    //@{
    /*
     * @brief called when we hit the end of input
     *
     * @return Returns the character at the current position or EOF.
     */
    virtual int underflow();

    /*
     * @brief called when we hit the end of output
     *
     * @param c The character to store at the current put position
     * @return Returns EOF if the function failed. Any other value on success.
     */
    virtual int overflow(int c);

    /*
     * @brief synchronize the buffer
     *
     * @return Returns 0 on success or -1 on failure.
     */
    virtual int sync();

    /*
     * @brief Seek to an offset position in a stream.
     *
     * @param off Offset value relative to way paramter
     * @param way The seek direction. One of ios::beg, ios::cur, and ios::end.
     * @param which Which pointer to modify. One of ios::in, ios::out,
     * or both masked together.
     * @return Returns the new position or an invalid position on failure.
     */
#if( LL_WINDOWS || __GNUC__ > 2)
    virtual pos_type seekoff(
        off_type off,
        std::ios::seekdir way,
        std::ios::openmode which);
#else
    virtual streampos seekoff(
        streamoff off,
        std::ios::seekdir way,
        std::ios::openmode which);
#endif

    /*
     * @brief Get s sequence of characters from the input
     *
     * @param dst Pointer to a block of memory to accept the characters
     * @param length Number of characters to be read
     * @return Returns the number of characters read
     */
    //virtual streamsize xsgetn(char* dst, streamsize length);

    /*
     * @brief Write some characters to output
     *
     * @param src Pointer to a sequence of characters to be output
     * @param length Number of characters to be put
     * @return Returns the number of characters written
     */
    //virtual streamsize xsputn(char* src, streamsize length);
    //@}

protected:
    // This channels we are working on.
    LLChannelDescriptors mChannels;

    // The buffer we work on
    LLBufferArray* mBuffer;
};


/**
 * @class LLBufferStream
 * @brief This implements an istream based wrapper around an LLBufferArray.
 *
 * This class does not own the buffer array, and does not hold a
 * shared pointer to it. Since the class itself is fairly ligthweight,
 * just make one on the stack when needed and let it fall out of
 * scope.
 */
class LLBufferStream : public std::iostream
{
public:
    LLBufferStream(
        const LLChannelDescriptors& channels,
        LLBufferArray* buffer);
    ~LLBufferStream();

protected:
    LLBufferStreamBuf mStreamBuf;
};


#endif // LL_LLBUFFERSTREAM_H