CLucene - a full-featured, c++ search engine
API Documentation
00001 /*------------------------------------------------------------------------------ 00002 * Copyright (C) 2003-2006 Jos van den Oever 00003 * 00004 * Distributable under the terms of either the Apache License (Version 2.0) or 00005 * the GNU Lesser General Public License, as specified in the COPYING file. 00006 ------------------------------------------------------------------------------*/ 00007 /* This file is part of Strigi Desktop Search 00008 * 00009 * Copyright (C) 2006 Jos van den Oever <jos@vandenoever.info> 00010 * 00011 * This library is free software; you can redistribute it and/or 00012 * modify it under the terms of the GNU Library General Public 00013 * License as published by the Free Software Foundation; either 00014 * version 2 of the License, or (at your option) any later version. 00015 * 00016 * This library is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00019 * Library General Public License for more details. 00020 * 00021 * You should have received a copy of the GNU Library General Public License 00022 * along with this library; see the file COPYING.LIB. If not, write to 00023 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00024 * Boston, MA 02110-1301, USA. 00025 */ 00026 #ifndef BUFFEREDSTREAM_H 00027 #define BUFFEREDSTREAM_H 00028 00029 #include "streambase.h" 00030 #include "inputstreambuffer.h" 00031 #include <cassert> 00032 00033 namespace jstreams { 00034 00035 template <class T> 00036 class BufferedInputStream : public StreamBase<T> { 00037 private: 00038 bool finishedWritingToBuffer; 00039 InputStreamBuffer<T> buffer; 00040 00041 void writeToBuffer(int32_t minsize); 00042 int32_t read_(const T*& start, int32_t min, int32_t max); 00043 protected: 00052 virtual int32_t fillBuffer(T* start, int32_t space) = 0; 00053 // this function might be useful if you want to reuse a bufferedstream 00054 void resetBuffer() {printf("implement 'resetBuffer'\n");} 00055 BufferedInputStream<T>(); 00056 public: 00057 int32_t read(const T*& start, int32_t min, int32_t max); 00058 int64_t reset(int64_t); 00059 virtual int64_t skip(int64_t ntoskip); 00060 }; 00061 00062 template <class T> 00063 BufferedInputStream<T>::BufferedInputStream() { 00064 finishedWritingToBuffer = false; 00065 } 00066 00067 template <class T> 00068 void 00069 BufferedInputStream<T>::writeToBuffer(int32_t ntoread) { 00070 int32_t missing = ntoread - buffer.avail; 00071 int32_t nwritten = 0; 00072 while (missing > 0 && nwritten >= 0) { 00073 int32_t space; 00074 space = buffer.makeSpace(missing); 00075 T* start = buffer.readPos + buffer.avail; 00076 nwritten = fillBuffer(start, space); 00077 assert(StreamBase<T>::status != Eof); 00078 if (nwritten > 0) { 00079 buffer.avail += nwritten; 00080 missing = ntoread - buffer.avail; 00081 } 00082 } 00083 if (nwritten < 0) { 00084 finishedWritingToBuffer = true; 00085 } 00086 } 00087 template <class T> 00088 int32_t 00089 BufferedInputStream<T>::read(const T*& start, int32_t min, int32_t max) { 00090 if (StreamBase<T>::status == Error) return -2; 00091 if (StreamBase<T>::status == Eof) return -1; 00092 00093 // do we need to read data into the buffer? 00094 if (!finishedWritingToBuffer && min > buffer.avail) { 00095 // do we have enough space in the buffer? 00096 writeToBuffer(min); 00097 if (StreamBase<T>::status == Error) return -2; 00098 } 00099 00100 int32_t nread = buffer.read(start, max); 00101 00102 BufferedInputStream<T>::position += nread; 00103 if (BufferedInputStream<T>::position > BufferedInputStream<T>::size 00104 && BufferedInputStream<T>::size > 0) { 00105 // error: we read more than was specified in size 00106 // this is an error because all dependent code might have been labouring 00107 // under a misapprehension 00108 BufferedInputStream<T>::status = Error; 00109 BufferedInputStream<T>::error = "Stream is longer than specified."; 00110 nread = -2; 00111 } else if (BufferedInputStream<T>::status == Ok && buffer.avail == 0 00112 && finishedWritingToBuffer) { 00113 BufferedInputStream<T>::status = Eof; 00114 if (BufferedInputStream<T>::size == -1) { 00115 BufferedInputStream<T>::size = BufferedInputStream<T>::position; 00116 } 00117 // save one call to read() by already returning -1 if no data is there 00118 if (nread == 0) nread = -1; 00119 } 00120 return nread; 00121 } 00122 template <class T> 00123 int64_t 00124 BufferedInputStream<T>::reset(int64_t newpos) { 00125 if (StreamBase<T>::status == Error) return -2; 00126 // check to see if we have this position 00127 int64_t d = BufferedInputStream<T>::position - newpos; 00128 if (buffer.readPos - d >= buffer.start && -d < buffer.avail) { 00129 BufferedInputStream<T>::position -= d; 00130 buffer.avail += (int32_t)d; 00131 buffer.readPos -= d; 00132 StreamBase<T>::status = Ok; 00133 } 00134 return StreamBase<T>::position; 00135 } 00136 template <class T> 00137 int64_t 00138 BufferedInputStream<T>::skip(int64_t ntoskip) { 00139 const T *begin; 00140 int32_t nread; 00141 int64_t skipped = 0; 00142 while (ntoskip) { 00143 int32_t step = (int32_t)((ntoskip > buffer.size) ?buffer.size :ntoskip); 00144 nread = read(begin, 1, step); 00145 if (nread <= 0) { 00146 return skipped; 00147 } 00148 ntoskip -= nread; 00149 skipped += nread; 00150 } 00151 return skipped; 00152 } 00153 } 00154 00155 #endif