/** * @file mime-inputsource.h * @brief The base class of the MIME input source * @author Andreas Aardal Hanssen * @date 2002-2005 */ #ifndef mime_inputsource_h_included #define mime_inputsource_h_included #include #include namespace Binc { class MimeInputSource { public: inline MimeInputSource(int fd, unsigned int start = 0); virtual inline ~MimeInputSource(); virtual inline bool fillInputBuffer(); virtual inline void reset(); inline void seek(unsigned int offset); inline bool getChar(char *c); inline void ungetChar(); inline int getFileDescriptor() const; inline unsigned int getOffset() const; private: int fd; char data[16384]; unsigned int offset; unsigned int tail; unsigned int head; unsigned int start; char lastChar; }; inline MimeInputSource::MimeInputSource(int fd, unsigned int start) { this->fd = fd; this->start = start; offset = 0; tail = 0; head = 0; lastChar = '\0'; memset(data, '\0', sizeof(data)); seek(start); } inline MimeInputSource::~MimeInputSource() {} inline bool MimeInputSource::fillInputBuffer() { char raw[4096]; ssize_t nbytes = read(fd, raw, sizeof(raw)); if (nbytes <= 0) { // FIXME: If ferror(crlffile) we should log this. return false; } for (ssize_t i = 0; i < nbytes; ++i) { const char c = raw[i]; if (c == '\r') { if (lastChar == '\r') { data[tail++ & (0x4000 - 1)] = '\r'; data[tail++ & (0x4000 - 1)] = '\n'; } } else if (c == '\n') { data[tail++ & (0x4000 - 1)] = '\r'; data[tail++ & (0x4000 - 1)] = '\n'; } else { if (lastChar == '\r') { data[tail++ & (0x4000 - 1)] = '\r'; data[tail++ & (0x4000 - 1)] = '\n'; } data[tail++ & (0x4000 - 1)] = c; } lastChar = c; } return true; } inline void MimeInputSource::reset() { offset = head = tail = 0; lastChar = '\0'; if (fd != -1) lseek(fd, 0, SEEK_SET); } inline void MimeInputSource::seek(unsigned int seekToOffset) { if (offset > seekToOffset) reset(); char c; int n = 0; while (seekToOffset > offset) { if (!getChar(&c)) break; ++n; } } inline bool MimeInputSource::getChar(char *c) { if (head == tail && !fillInputBuffer()) return false; *c = data[head++ & (0x4000 - 1)]; ++offset; return true; } inline void MimeInputSource::ungetChar() { --head; --offset; } inline int MimeInputSource::getFileDescriptor() const { return fd; } inline unsigned int MimeInputSource::getOffset() const { return offset; } } extern Binc::MimeInputSource *mimeSource; #endif