/*------------------------------------------------------------------------------ * Copyright (C) 2003-2006 Jos van den Oever * * Distributable under the terms of either the Apache License (Version 2.0) or * the GNU Lesser General Public License, as specified in the COPYING file. ------------------------------------------------------------------------------*/ /* This file is part of Strigi Desktop Search * * Copyright (C) 2006 Jos van den Oever * * 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 STREAMBASE_H #define STREAMBASE_H #include #define INT32MAX 0x7FFFFFFFL namespace jstreams { enum StreamStatus { Ok, Eof, Error }; /** * @short Base class for stream read access to many different file types. * * This class is based on the interface java.io.InputStream. It allows * for uniform access to streamed resources. * The main difference with the java equivalent is a performance improvement. * When reading data, data is not copied into a buffer provided by the caller, * but a pointer to the read data is provided. This makes this interface * especially useful for deriving from it and implementing filterers or * transformers. */ // java mapping: long=int64, int=int32, byte=uint8_t template class StreamBase { protected: int64_t size; int64_t position; std::string error; StreamStatus status; public: StreamBase() :size(-1), position(0), status(Ok){ } virtual ~StreamBase(){} /** * @brief Return a string representation of the last error. * If no error has occurred, an empty string is returned. **/ const char* getError() const { return error.c_str(); } StreamStatus getStatus() const { return status; } /** * @brief Get the current position in the stream. * The value obtained from this function can be used to reset the stream. **/ int64_t getPosition() const { return position; } /** * @brief Return the size of the stream. * If the size of the stream is unknown, -1 * is returned. If the end of the stream has been reached the size is * always known. **/ int64_t getSize() const { return size; } /** * @brief Reads characters from the stream and sets \a start to * the first character that was read. * * If @p ntoread is @c 0, then at least one character will be read. * * @param start Pointer passed by reference that will be set to point to * the retrieved array of characters. If the end of the stream * is encountered or an error occurs, the value of @p start * is undefined. * @param min The number of characters to read from the stream. * @param max The maximum number of characters to read from the stream. * @return the number of characters that were read. If -1 is returned, the * end of the stream has been reached. If -2 is returned, an error * has occurred. **/ virtual int32_t read(const T*& start, int32_t min, int32_t max) = 0; /** * Skip @param ntoskip bytes. Unless an error occurs or the end of file is * encountered, this amount of bytes is skipped. * This function returns new position in the stream. **/ virtual int64_t skip(int64_t ntoskip); /** * @brief Repositions this stream to given requested position. * Reset is guaranteed to work after a successful call to read(), * when the new position is in the range of the data returned by read(). * This means that @p pos must lie between than the position * corresponding to the start parameter (x) of the read function * and the position corresponding to the last position in the returned * buffer (x + nread). **/ virtual int64_t reset(int64_t pos) = 0; int64_t mark(int32_t readlimit) { int64_t p = getPosition(); const T* ptr; read(ptr, readlimit, -1); return reset(p); } }; #define SKIPSTEP 1024 template int64_t StreamBase::skip(int64_t ntoskip) { const T *begin; int32_t nread; int64_t skipped = 0; while (ntoskip) { int32_t step = (int32_t)((ntoskip > SKIPSTEP) ?SKIPSTEP :ntoskip); nread = read(begin, 1, step); if (nread < -1 ) { // an error occurred return nread; } else if (nread < 1) { ntoskip = 0; } else { skipped += nread; ntoskip -= nread; } } return skipped; } } // end namespace jstreams #endif