diff options
Diffstat (limited to 'src/iodevice.cc')
-rw-r--r-- | src/iodevice.cc | 283 |
1 files changed, 283 insertions, 0 deletions
diff --git a/src/iodevice.cc b/src/iodevice.cc new file mode 100644 index 0000000..7197354 --- /dev/null +++ b/src/iodevice.cc @@ -0,0 +1,283 @@ +/** -------------------------------------------------------------------- + * @file iodevice.cc + * @brief Implementation of the IODevice class. + * @author Andreas Aardal Hanssen + * @date 2002, 2003 + * ----------------------------------------------------------------- **/ +#include "iodevice.h" +#include "convert.h" // BincStream +#include "session.h" // getEnv/hasEnv + +#include <stdlib.h> +#include <unistd.h> + +using namespace ::std; +using namespace ::Binc; + +//------------------------------------------------------------------------ +IODevice::IODevice(int f) : flags(f | IsEnabled), + maxInputBufferSize(0), + maxOutputBufferSize(0), + timeout(0), + readCount(0), writeCount(0), + outputLevel(ErrorLevel), + outputLevelLimit(ErrorLevel), + error(Unknown), errorString("Unknown device error"), + dumpfd(0) +{ +} + +//------------------------------------------------------------------------ +IODevice::~IODevice(void) +{ +} + +//------------------------------------------------------------------------ +IODevice &IODevice::operator <<(ostream &(*source)(ostream &)) +{ + if (!(flags & IsEnabled) || outputLevel > outputLevelLimit) + return *this; + + static std::ostream &(*endl_funcptr)(ostream &) = endl; + + if (source != endl_funcptr) return *this; + + outputBuffer << "\r\n"; + + if (dumpfd) ::write(dumpfd, "\r\n", 2); + + if (flags & FlushesOnEndl) + flush(); + else if (flags & HasOutputLimit) + if (outputBuffer.getSize() > maxOutputBufferSize) + flush(); + + return *this; +} + +//------------------------------------------------------------------------ +bool IODevice::canRead(void) const +{ + return false; +} + +//------------------------------------------------------------------------ +void IODevice::clear() +{ + if (!(flags & IsEnabled)) return; + + inputBuffer.clear(); + outputBuffer.clear(); +} + +//------------------------------------------------------------------------ +bool IODevice::flush() +{ + if (!(flags & IsEnabled)) return true; + + WriteResult writeResult = WriteWait; + do { + unsigned int s = outputBuffer.getSize(); + if (s == 0) break; + if (!waitForWrite()) return false; + writeResult = write(); + if (writeResult == WriteError) return false; + writeCount += s - outputBuffer.getSize(); + } while (outputBuffer.getSize() > 0 && writeResult == WriteWait); + + outputBuffer.clear(); + + return true; +} + +//------------------------------------------------------------------------ +void IODevice::setFlags(unsigned int f) +{ + flags |= f; +} + +//------------------------------------------------------------------------ +void IODevice::clearFlags(unsigned int f) +{ + flags &= ~f; +} + +//------------------------------------------------------------------------ +void IODevice::setMaxInputBufferSize(unsigned int max) +{ + maxInputBufferSize = max; +} + +//------------------------------------------------------------------------ +void IODevice::setMaxOutputBufferSize(unsigned int max) +{ + maxOutputBufferSize = max; +} + +//------------------------------------------------------------------------ +void IODevice::setTimeout(unsigned int t) +{ + timeout = t; + + if (t) + flags |= HasTimeout; + else + flags &= ~HasTimeout; +} + +//------------------------------------------------------------------------ +unsigned int IODevice::getTimeout(void) const +{ + return timeout; +} + +//------------------------------------------------------------------------ +void IODevice::setOutputLevel(LogLevel level) +{ + outputLevel = level; +} + +//------------------------------------------------------------------------ +IODevice::LogLevel IODevice::getOutputLevel(void) const +{ + return outputLevel; +} + +//------------------------------------------------------------------------ +void IODevice::setOutputLevelLimit(LogLevel level) +{ + outputLevelLimit = level; +} + +//------------------------------------------------------------------------ +IODevice::LogLevel IODevice::getOutputLevelLimit(void) const +{ + return outputLevelLimit; +} + +//------------------------------------------------------------------------ +bool IODevice::readStr(string *dest, unsigned int max) +{ + // If max is 0, fill the input buffer once only if it's empty. + if (!max && inputBuffer.getSize() == 0 && !fillInputBuffer()) return false; + + // If max is != 0, wait until we have max. + while (max && inputBuffer.getSize() < max) { + if (!fillInputBuffer()) return false; + } + + unsigned int bytesToRead = max ? max : inputBuffer.getSize(); + *dest += inputBuffer.str().substr(0, bytesToRead); + if (dumpfd) { + ::write(dumpfd, inputBuffer.str().substr(0, bytesToRead).c_str(), bytesToRead); + } + + inputBuffer.popString(bytesToRead); + readCount += bytesToRead; + + return true; +} + +//------------------------------------------------------------------------ +bool IODevice::readChar(char *dest) +{ + if (inputBuffer.getSize() == 0 && !fillInputBuffer()) return false; + + char c = inputBuffer.popChar(); + if (dest) *dest = c; + if (dumpfd) ::write(dumpfd, &c, 1); + + ++readCount; + + return true; +} + +//------------------------------------------------------------------------ +void IODevice::unreadChar(char c) +{ + inputBuffer.unpopChar(c); +} + +//------------------------------------------------------------------------ +void IODevice::unreadStr(const string &s) +{ + inputBuffer.unpopStr(s); +} + +//------------------------------------------------------------------------ +bool IODevice::skipTo(char c) +{ + char dest = '\0'; + do { + if (!readChar(&dest)) return false; + if (dumpfd) ::write(dumpfd, &dest, 1); + } while (c != dest); + + return true; +} + +//------------------------------------------------------------------------ +string IODevice::service(void) const +{ + return "nul"; +} + +//------------------------------------------------------------------------ +bool IODevice::waitForWrite(void) const +{ + return false; +} + +//------------------------------------------------------------------------ +bool IODevice::waitForRead(void) const +{ + return false; +} + +//------------------------------------------------------------------------ +IODevice::WriteResult IODevice::write(void) +{ + return WriteError; +} + +//------------------------------------------------------------------------ +bool IODevice::fillInputBuffer(void) +{ + return false; +} + +//------------------------------------------------------------------------ +IODevice::Error IODevice::getLastError(void) const +{ + return error; +} + +//------------------------------------------------------------------------ +string IODevice::getLastErrorString(void) const +{ + return errorString; +} + +//------------------------------------------------------------------------ +unsigned int IODevice::getReadCount(void) const +{ + return readCount; +} + +//------------------------------------------------------------------------ +unsigned int IODevice::getWriteCount(void) const +{ + return writeCount; +} + +//------------------------------------------------------------------------ +void IODevice::enableProtocolDumping(void) +{ + BincStream ss; + ss << "/tmp/bincimap-dump-" << (int) time(0) << "-" + << Session::getInstance().getIP() << "-XXXXXX"; + char *safename = strdup(ss.str().c_str()); + dumpfd = mkstemp(safename); + if (dumpfd == -1) dumpfd = 0; + delete[] safename; +} |