diff options
Diffstat (limited to 'src/include/iodevice.h')
-rw-r--r-- | src/include/iodevice.h | 382 |
1 files changed, 382 insertions, 0 deletions
diff --git a/src/include/iodevice.h b/src/include/iodevice.h new file mode 100644 index 0000000..070ac3f --- /dev/null +++ b/src/include/iodevice.h @@ -0,0 +1,382 @@ +/** -------------------------------------------------------------------- + * @file iodevice.h + * @brief Declaration of the IODevice class. + * @author Andreas Aardal Hanssen + * @date 2002, 2003 + * ----------------------------------------------------------------- **/ +#ifndef iodevice_h_included +#define iodevice_h_included + +#include "convert.h" // BincStream +//#include <iostream> +#include <string> +#include <unistd.h> // ::write + +const char CMS_END_OF_LINE[4] = { 0x0d, '\n', 0x00, 0x00 }; + +namespace Binc { + /*! + \class IODevice + \brief The IODevice class provides a framework for reading and + writing to device. + + Implement new devices by inheriting this class and overloading all + virtual methods. + + service() returns the service that the specific device is used + for. Two values are "log" and "client". + + \sa IOFactory, MultilogDevice, SyslogDevice, StdIODevice, SSLDevice + */ + class IODevice { + public: + /*! + Standard options for an IODevice. + */ + enum Flags { + None = 0, + FlushesOnEndl = 1 << 0, + HasInputLimit = 1 << 1, + HasOutputLimit = 1 << 2, + IsEnabled = 1 << 3, + HasTimeout = 1 << 4 + }; + + /*! + Errors from when an operation returned false. + */ + enum Error { + Unknown, + Timeout + }; + + /*! + Constructs an invalid IODevice. + + Instances of IODevice perform no operations, and all boolean + functions always return false. This constructor is only useful + if called from a subclass that reimplements all virtual methods. + */ + IODevice(int f = 0); + + /*! + Destructs an IODevice; does nothing. + */ + virtual ~IODevice(void); + + /*! + Clears all data in the input and output buffers. + */ + void clear(void); + + /*! + Sets one or more flags. + \param f A bitwise OR of flags from the Flags enum. + */ + void setFlags(unsigned int f); + + /*! + Clears one or more flags. + \param f A bitwise OR of flags from the Flags enum. + */ + void clearFlags(unsigned int f); + + /*! + Sets the maximum allowed input buffer size. If this size is + non-zero and exceeded, reading from the device will fail. This + functionality is used to prevent clients from forcing this class + to consume so much memory that the program crashes. + + Setting the max input buffer size to 0 disables the input size + limit. + + \param max The maximum input buffer size in bytes. + */ + void setMaxInputBufferSize(unsigned int max); + + /*! + Sets the maximum allowed output buffer size. If this size is + non-zero and exceeded, flush() is called implicitly. + + Setting the max output buffer size to 0 disables the output size + limit. This is generally discouraged. + + As a contrast to setMaxInputBufferSize(), this function is used + to bundle up consequent write calls, allowing more efficient use + of the underlying device as larger blocks of data are written at + a time. + + \param max The maximum output buffer size in bytes. + */ + void setMaxOutputBufferSize(unsigned int max); + + /*! + Sets the device's internal timeout in seconds. This timeout is + used both when waiting for data to read and for waiting for the + ability to write. + + If this timeout is exceeded, the read or write function that + triggered the timeout will fail. + + Setting the timeout to 0 disables the timeout. + + \param t The timeout in seconds. + \sa getTimeout() + */ + void setTimeout(unsigned int t); + + /*! + Returns the timeout in seconds, or 0 if there is no timeout. + + \sa setTimeout() + */ + unsigned int getTimeout(void) const; + + enum LogLevel { + ErrorLevel, + InfoLevel, + WarningLevel, + DebugLevel + }; + + /*! + Sets the output level for the following write operations on this + device. + + The output level is a number which gives the following write + operations a priority. You can use setOutputLevelLimit() to + filter the write operations valid for different operating modes. + This enables you to have certain write operations ignored. + + For instance, if the output level is set to 0, then "Hello" is + written, and the output level is set to 1, followed by writing + "Daisy", the output level limit value will decive wether only + "Hello" is written, or if also "Daisy" is written. + + A low value of the level gives higher priority, and a high level + will give low priority. The default value is 0, and write + operations that are done with output level 0 are never ignored. + + \param level The output level + \sa getOutputLevel(), setOutputLevelLimit() + */ + void setOutputLevel(LogLevel level); + + /*! + Returns the current output level. + + \sa setOutputLevel() + */ + LogLevel getOutputLevel(void) const; + + /*! + Sets the current output level limit. Write operations with a + level higher than the output level limit are ignored. + + \param level The output level limit + \sa setOutputLevel() + */ + void setOutputLevelLimit(LogLevel level); + + /*! + Returns the current output level limit. + + \sa setOutputLevelLimit() + */ + LogLevel getOutputLevelLimit(void) const; + + /*! + Returns the number of bytes that have been read from this device + since it was created. + */ + unsigned int getReadCount(void) const; + + /*! + Returns the number of bytes that have been written to this + device since it was created. + */ + unsigned int getWriteCount(void) const; + + /*! + Calling this function enables the built-in protocol dumping feature in + the device. All input and output to this device will be dumped to a file + in /tmp. + */ + void enableProtocolDumping(void); + + /*! + Writes data to the device. Depending on the value of the max + output buffer size, the data may not be written immediately. + + \sa setMaxOutputBufferSize() + */ + template <class T> IODevice &operator << (const T &source); + + /*! + Writes data to the device. This function specializes on standard + ostream derivates, such as std::endl. + */ + IODevice &operator << (std::ostream &(*source)(std::ostream &)); + + /*! + Returns true if data can be read from the device; otherwise + returns false. + */ + virtual bool canRead(void) const; + + /*! + Reads data from the device, and stores this in a string. Returns + true on success; otherwise returns false. + + \param dest The incoming data is stored in this string. + \param max No more than this number of bytes is read from the + device. + */ + bool readStr(std::string *dest, unsigned int max = 0); + + /*! + Reads exactly one byte from the device and stores this in a + char. Returns true on success; otherwise returns false. + + \param dest The incoming byte is stored in this char. + */ + bool readChar(char *dest = 0); + + /*! + FIXME: add docs + */ + void unreadChar(char c); + + /*! + FIXME: add docs + */ + void unreadStr(const std::string &s); + + /*! + Reads characters from the device, until and including one + certain character is found. All read characters are discarded. + + This function can be used to skip to the beginning of a line, + with the terminating character being '\n'. + + \param The certain character. + */ + bool skipTo(char c); + + /*! + Flushes the output buffer. Writes all data in the output buffer + to the device. + */ + bool flush(void); + + /*! + Returns the type of error that most recently occurred. + */ + Error getLastError(void) const; + + /*! + Returns a human readable description of the error that most + recently occurred. If no known error has occurred, this method + returns "Unknown error". + */ + std::string getLastErrorString(void) const; + + /*! + Returns the type of service provided by this device. Two valid + return values are "client" and "log". + */ + virtual std::string service(void) const; + + protected: + /*! + Waits until data can be written to the device. If the timeout is + 0, this function waits indefinitely. Otherwise, it waits until + the timeout has expired. + + If this function returns true, data can be written to the + device; otherwise, getLastError() must be checked to determine + whether a timeout occurred or whether an error with the device + prevents further writing. + */ + virtual bool waitForWrite(void) const; + + /*! + Waits until data can be read from the device. + + \sa waitForWrite() + */ + virtual bool waitForRead(void) const; + + /*! + Types of results from a write. + */ + enum WriteResult { + WriteWait = 0, + WriteDone = 1 << 0, + WriteError = 1 << 1 + }; + + /*! + Writes as much data as possible to the device. If some but not + all data was written, returns WriteWait. If all data was + written, returns WriteDone. If an error occurred, returns + WriteError. + */ + virtual WriteResult write(void); + + /*! + Reads data from the device, and stores it in the input buffer. + Returns true on success; otherwise returns false. + + This method will fail if there is no more data available, if a + timeout occurred or if an error with the device prevents more + data from being read. + + The number of bytes read from the device is undefined. + */ + virtual bool fillInputBuffer(void); + + BincStream inputBuffer; + BincStream outputBuffer; + + protected: + unsigned int flags; + unsigned int maxInputBufferSize; + unsigned int maxOutputBufferSize; + + unsigned int timeout; + + unsigned int readCount; + unsigned int writeCount; + + LogLevel outputLevel; + LogLevel outputLevelLimit; + + mutable Error error; + mutable std::string errorString; + + int dumpfd; + }; + + //---------------------------------------------------------------------- + template <class T> IODevice &IODevice::operator << (const T &source) + { + if ((flags & IsEnabled) && outputLevel <= outputLevelLimit) { + outputBuffer << source; + + if (dumpfd) { + BincStream ss; + ss << source; + ::write(dumpfd, ss.str().c_str(), ss.getSize()); + } + + if (flags & HasInputLimit) + if (outputBuffer.getSize() > maxOutputBufferSize) + flush(); + } + + return *this; + } +} + +#endif |