/** -------------------------------------------------------------------- * @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 #include 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; }