/***************************************************************************
                          stream.h  -  description
                             -------------------
    begin                : Tue Nov 9 1999
    copyright            : (C) 1999 by Martin Preuss
    email                : martin@aquamaniac.de
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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; either          *
 *   version 2.1 of the License, or (at your option) any later version.    *
 *                                                                         *
 *   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., 59 Temple Place, Suite 330, Boston,                 *
 *   MA  02111-1307  USA                                                   *
 *                                                                         *
 ***************************************************************************/

/*
 */

#ifndef C_STREAM_H
#define C_STREAM_H

#define STREAM_LINEMODE_UNIX 	  1
#define STREAM_LINEMODE_DOS  	  2

#define STREAM_TIMEOUT    	120
#define STREAM_BUFFERSIZE     1024

#define STREAM_CR		 13
#define STREAM_LF		 10

#include <list>

#include <openhbci/error.h>


namespace HBCI {

/**
 * @short This is a base class for filtering of streams.
 * @author Martin Preuss <martin@aquamaniac.de>
 */
class DLLIMPORT StreamFilter {
private:
    bool _isactive;
public:
    StreamFilter(): _isactive(true) {};
    virtual ~StreamFilter() {};
    virtual void encode(string &data)=0;
    virtual void decode(string &data)=0;
    bool isActive() const { return _isactive;};
    void setActive(bool isactive) { _isactive=isactive;};
};


/**
 * @short This is an example stream filter. 
 *
 * It just strips off the most significant
 * bit of all bytes.
 * @author Martin Preuss <martin@aquamaniac.de>
 */
class DLLIMPORT StreamFilter_7bit : public StreamFilter {
public:
    StreamFilter_7bit();
    ~StreamFilter_7bit();
    /**
     * This method is called when data is put to the stream target.
     * @author Martin Preuss <martin@aquamaniac.de>
     * @param data reference to a buffer that contains the data. The
     * filter should return the encoded data in this variable, too.
     */
    void encode(string &data);

    /**
     * This method is called when data is read from the stream source.
     * @author Martin Preuss <martin@aquamaniac.de>
     * @param data reference to a buffer that contains the data. The
     * filter should return the decoded data in this variable, too.
     */
    void decode(string &data);
};


/**
 * @short This class provides basic streaming functionality. 
 *
 * It can be used on files
 * and on network connections. Well, it can be used for ANY kind of source
 * or target. The only thing you have to do is to provide the following
 * methods:
 * - readData
 * - writeData
 *
 * @author Martin Preuss <martin@aquamaniac.de>
 */
class Stream {
private:
    bool _newbuffers;

    unsigned int _linemode;
    long _timeout;
    unsigned int _buffersize;
    
    string _inbuffer;
    unsigned int _inpos;
    string _outbuffer;
    unsigned int _outpos;

    unsigned int _totalread;
    unsigned int _totalwritten;
    list<StreamFilter*> _filters;

    bool _eof;
    
    void _fillBuffer();
    void _flushBuffer();
    void _getData(string &data, unsigned int size);
    void _putData(string &data);

public:

    /**
     * Constructor.
     * @author Martin Preuss<martin@aquamaniac.de>
     * @param buffersize size of internal io buffers
     */
    Stream(unsigned int buffersize);

    /**
     * Constructor. Use this one if you have fixed buffers to read/write.
     * The main use of this constructor is to implement streams which
     * read from/write to buffers. The contents of the buffers are copied
     * into internal buffers, so you can do to your copies whatever you like.
     * @author Martin Preuss<martin@aquamaniac.de>
     * @param inbuffer input buffer
     * @param outbuffer output buffer
     */
    Stream(string inbuffer, string outbuffer);

    virtual ~Stream();

    /**
     * Reads data from the stream.
     * This method has to be implemented by derived classes.
     * @author Martin Preuss<martin@aquamaniac.de>
     * @param data reference to a string to receive the data read
     * @param size maximum size of the data to be received
     * @param timeout timeout for reading in seconds
     */
    virtual void readData(string &data, unsigned int size, long timeout)=0;

    /**
     * Writes data into the stream.
     * This method has to be implemented by derived classes.
     * @author Martin Preuss<martin@aquamaniac.de>
     * @param data reference to a string to receive the data read
     * @param timeout timeout for writing in seconds
     */
    virtual void writeData(string &data, long timeout)=0;

    /**
     * Checks if the end of file has been reached.
     * @author Martin Preuss<martin@aquamaniac.de>
     * @return true if eof met, false otherwise
     */
    bool eof();

    /**
     * Reads a character from the stream.
     * @author Martin Preuss<martin@aquamaniac.de>
     * @return character read (-1 if end of file)
     */
    int readChar();
    
    /**
     * Peeks a character from the stream. That means successive calls
     * to this method will return the same character without advancing any
     * pointers.
     * @author Martin Preuss<martin@aquamaniac.de>
     * @return character read (-1 if end of file)
     */
    int peekChar();

    /**
     * Writes a character into the stream.
     * @author Martin Preuss<martin@aquamaniac.de>
     * @param c character to write
     */
    void writeChar(char c);

    /**
     * Reads data directly from the stream. All filters are applied, though.
     * If there is any data in the input buffer, then this data will be
     * returned first.
     * @author Martin Preuss<martin@aquamaniac.de>
     * @param data reference to a string to receive the data
     * @param size maximum size of the data to be read (the resulting string
     * may even be longer because of the filtering).
     */
    void readRaw(string &data, unsigned int size);

    /**
     * Reads data with EXACTLY the given size directly from the stream.
     * All filters are applied, though.
     * If there is any data in the input buffer, then this data will be
     * returned first.
     * @author Martin Preuss<martin@aquamaniac.de>
     * @param data reference to a string to receive the data
     * @param size maximum size of the data to be read (the resulting string
     * may even be longer because of the filtering).
     */
    bool readRawForced(string &data, unsigned int size);

    /**
     * Writes directly into the stream. All filters are applied.
     * If there is still data in the outpuffer this buffer will be flushed
     * first.
     * @author Martin Preuss<martin@aquamaniac.de>
     * @param s reference to a string to be written
     */
    void writeRaw(string &s);

    /**
     * Reads a text line from the stream.
     * The end of line markers are <LF> or <CRLF>, according to the
     * current line mode (<CRLF> for DOS).
     * @author Martin Preuss<martin@aquamaniac.de>
     * @param data reference to a string to receive the data
     * @param linesize maximum size of the line to read, this will never
     * be exceeded.
     */
    void readLine(string &data, unsigned int linesize);

    /**
     * Writes a string into the stream.
     * @author Martin Preuss<martin@aquamaniac.de>
     * @param s reference to the string to be written
     */
    void writeString(string s);

    /**
     * Writes a line into the stream (including end-of-line markers).
     * The end of line markers are <LF> or <CRLF>, according to the
     * current line mode (<CRLF> for DOS).
     * @author Martin Preuss<martin@aquamaniac.de>
     * @param s string to be written
     */
    void writeLine(string s);

    /**
     * Writes the content of the output buffer into the stream, if any.
     * @author Martin Preuss<martin@aquamaniac.de>
     */
    void flushBuffer();

    /**
     * Inserts a new filter at the beginning of the list.
     * When writing data into a stream, all filters will be asked to
     * encode the data, beginning with the first filter.
     * When reading data from a stream, the list of filters will be walked
     * through in reverse order.
     * @author Martin Preuss<martin@aquamaniac.de>
     * @param f filter to be inserted at the beginning
     */
    void insertFilter(StreamFilter *f);
    
    /**
     * Inserts a new filter at the end of the list.
     * When writing data into a stream, all filters will be asked to
     * encode the data, beginning with the first filter.
     * When reading data from a stream, the list of filters will be walked
     * through in reverse order.
     * @author Martin Preuss<martin@aquamaniac.de>
     * @param f filter to be inserted at the end
     */
    void appendFilter(StreamFilter *f);

    /**
     * Returns the current read position in the stream.
     * @author Martin Preuss<martin@aquamaniac.de>
     */
    unsigned int readPos();

    /**
     * Returns the current read position in the stream.
     * @author Martin Preuss<martin@aquamaniac.de>
     */
    unsigned int writePos();

    /**
     * Returns the current line mode.
     * @author Martin Preuss<martin@aquamaniac.de>
     */
    unsigned int lineMode() const { return _linemode;};

    /**
     * Sets the current line mode (STREAM_LINEMODE_UNIX or
     * STREAM_LINEMODE_DOS).
     * @author Martin Preuss<martin@aquamaniac.de>
     * @param m new mode
     */
    void setLineMode(unsigned int m) { _linemode=m; };

    /**
     * Returns the current timeout in seconds.
     */
    long timeOut() const { return _timeout;};

    /**
     * Sets a new timeout value (in seconds).
     */
    void setTimeout(long timeout) { _timeout=timeout;};

};



} /* namespace HBCI */





#endif

