You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdelibs/tdecore/kbufferedio.h

301 lines
11 KiB

/*
* This file is part of the KDE libraries
* Copyright (C) 2001 Thiago Macieira <thiago.macieira@kdemail.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef KBUFFEREDIO_H
#define KBUFFEREDIO_H
#include <tqcstring.h>
#include <tqptrlist.h>
#include "kasyncio.h"
class TDEBufferedIOPrivate;
/**
* This abstract class implements basic functionality for buffered
* input/output.
*
* Through the available methods, you can find out how many bytes are
* available for reading, how many are still unsent and you can peek at
* the buffered data.
*
* This class was intentionally written to resemble TQSocket, because
* KExtendedSocket is a subclass of this one. This is so that applications
* written using QSocket's buffering characteristics will be more easily
* ported to the more powerful KExtendedSocket class.
*
* TDEBufferedIO already provides a powerful internal buffering algorithm. However,
* this does not include the I/O itself, which must be implemented in
* derived classes. Thus, to implement a class that does some I/O, you must
* override, in addition to the pure virtual TQIODevice methods, these two:
* @li closeNow()
* @li waitForMore()
*
* If your derived class reimplements the buffering algorithm, you must then
* decide which buffering functions to override. For instance, you may want to
* change the protected functions like feedReadBuffer() and consumeReadBuffer().
*
* @author Thiago Macieira <thiagom@mail.com>
* @short Buffered I/O
*/
class TDECORE_EXPORT TDEBufferedIO: public KAsyncIO
{
TQ_OBJECT
protected:
// no default public constructor
TDEBufferedIO();
public:
/**
* The modes for closed() signal
*/
enum closeModes
{
availRead = 0x01,
dirtyWrite = 0x02,
involuntary = 0x10,
delayed = 0x20,
closedNow = 0x40
};
/**
* Destroys this class. The flushing of the buffers is implementation dependant.
* The default implementation discards the contents
*/
virtual ~TDEBufferedIO();
/**
* Closes the stream now, discarding the contents of the
* write buffer. That is, we won't try to flush that
* buffer before closing. If you want that buffer to be
* flushed, you can call TQIODevice::flush(), which is blocking, and
* then closeNow, or you can call TQIODevice::close() for a delayed
* close.
*/
virtual void closeNow() = 0;
/**
* Sets the internal buffer size to value.
*
* Not all implementations support this.
*
* The parameters may be 0 to make the class unbuffered or -1
* to let the class choose the size (which may be unlimited) or
* -2 to leave the buffer size untouched.
*
* Note that setting the write buffer size to any value smaller than
* the current size of the buffer will force it to flush first,
* which can make this call blocking.
*
* The default implementation does not support setting the buffer
* sizes. You can only call this function with values -1 for "don't care"
* or -2 for "unchanged"
* @param rsize the size of the read buffer
* @param wsize the size of the write buffer
* @return true if setting both was ok. If false is returned, the
* buffers were left unchanged.
*/
virtual bool setBufferSize(int rsize, int wsize = -2);
/**
* Returns the number of bytes available for reading in the read buffer
* @return the number of bytes available for reading
*/
#ifdef USE_QT3
virtual int bytesAvailable() const;
#endif // USE_QT3
#ifdef USE_QT4
virtual qint64 bytesAvailable() const;
#endif // USE_QT4
/**
* Waits for more data to be available and returns the amount of available data then.
*
* @param msec number of milliseconds to wait, -1 to wait forever
* @return -1 if we cannot wait (e.g., that doesn't make sense in this stream)
*/
virtual int waitForMore(int msec) = 0;
/**
* Returns the number of bytes yet to write, still in the write buffer
* @return the number of unwritten bytes in the write buffer
*/
#ifdef USE_QT3
virtual int bytesToWrite() const;
#endif // USE_QT3
#ifdef USE_QT4
virtual qint64 bytesToWrite() const;
#endif // USE_QT4
/**
* Checks whether there is enough data in the buffer to read a line
*
* The default implementation reads directly from inBuf, so if your
* implementation changes the meaning of that member, then you must override
* this function.
* @return true when there is enough data in the buffer to read a line
*/
virtual bool canReadLine() const;
// readBlock, peekBlock and writeBlock are not defined in this class (thus, left
// pure virtual) because this does not mean only reading and writing
// to the buffers. It may be necessary to do I/O to complete the
// transaction (e.g., user wants to read more than is in the buffer).
// Reading and writing to the buffer are available for access through
// protected member functions
/**
* Reads into the user buffer at most maxlen bytes, but does not
* consume that data from the read buffer. This is useful to check
* whether we already have the needed data to process something.
*
* This function may want to try and read more data from the system
* provided it won't block.
*
* @param data the user buffer pointer, at least maxlen bytes long
* @param maxlen the maximum length to be peeked
* @return the number of bytes actually copied.
*/
virtual int peekBlock(char *data, uint maxlen) = 0;
/**
* Unreads some data. That is, write the data to the beginning of the
* read buffer, so that next calls to readBlock or peekBlock will see
* this data instead.
*
* Note not all devices implement this since this could mean a semantic
* problem. For instance, sockets are sequential devices, so they won't
* accept unreading.
* @param data the data to be unread
* @param len the size of the data
* @return the number of bytes actually unread
*/
virtual int unreadBlock(const char *data, uint len);
signals:
/**
* This signal gets sent whenever bytes are written from the buffer.
* @param nbytes the number of bytes sent.
*/
void bytesWritten(int nbytes);
// There is no read signal here. We use the readyRead signal inherited
// from KAsyncIO for that purpose
/**
* This signal gets sent when the stream is closed. The @p state parameter
* will give the current state, in OR-ed bits:
* @li availRead: read buffer contains data to be read
* @li dirtyWrite: write buffer wasn't empty when the stream closed
* @li involuntary: the stream wasn't closed due to user request
* (i.e., call to close). Probably remote end closed it
* @li delayed: the stream was closed voluntarily by the user, but it
* happened only after the write buffer was emptied
* @li closedNow: the stream was closed voluntarily by the user, by
* explicitly calling closeNow, which means the
* write buffer's contents may have been discarded
* @param state the state (see function description)
*/
void closed(int state);
protected:
/**
* For an explanation on how this buffer work, please refer to the comments
* at the top of kbufferedio.cpp, @ref impldetails .
*/
TQPtrList<TQByteArray> inBuf;
/**
* For an explanation on how this buffer work, please refer to the comments
* at the top of kbufferedio.cpp, @ref impldetails .
*/
TQPtrList<TQByteArray> outBuf;
unsigned inBufIndex /** Offset into first input buffer. */,
outBufIndex /** Offset into first output buffer. */ ;
/**
* Consumes data from the input buffer.
* That is, this will copy the data stored in the input (read) buffer
* into the given @p destbuffer, as much as @p nbytes.
* @param nbytes the maximum amount of bytes to copy into the buffer
* @param destbuffer the destination buffer into which to copy the data
* @param discard whether to discard the copied data after the operation
* @return the real amount of data copied. If it is less than
* nbytes, then all the buffer was copied.
*/
virtual unsigned consumeReadBuffer(unsigned nbytes, char *destbuffer, bool discard = true);
/**
* Consumes data from the output buffer.
* Since this is called whenever we managed to send data out the wire, we
* can only discard this amount from the buffer. There is no copying and no
* "peeking" for the output buffer.
*
* Note this function should be called AFTER the data was sent. After it
* is called, the data is no longer available in the buffer. And don't pass
* wrong nbytes values.
* @param nbytes the amount of bytes to discard
*/
virtual void consumeWriteBuffer(unsigned nbytes);
/**
* Feeds data into the input buffer.
* This happens when we detected available data in the device and read it.
* The data will be appended to the buffer or inserted at the beginning,
* depending on whether @p atBeginning is set or not.
* @param nbytes the number of bytes in the buffer
* @param buffer the data that was read
* @param atBeginning whether to append or insert at the beginning
* @return the number of bytes that have been appended
*/
virtual unsigned feedReadBuffer(unsigned nbytes, const char *buffer, bool atBeginning = false);
/**
* Feeds data into the output buffer.
* This happens when the user told us to write some data.
* The data will be appended to the buffer.
* @param nbytes the number of bytes in the buffer
* @param buffer the data that is to be written
* @return the number of bytes that have been appended
*/
virtual unsigned feedWriteBuffer(unsigned nbytes, const char *buffer);
/**
* Returns the number of bytes in the read buffer
* @return the size of the read buffer in bytes
*/
virtual unsigned readBufferSize() const;
/**
* Returns the number of bytes in the write buffer
* @return the size of the write buffer in bytes
*/
virtual unsigned writeBufferSize() const;
protected:
virtual void virtual_hook( int id, void* data );
private:
TDEBufferedIOPrivate *d;
};
#endif // KBUFFEREDIO_H