strigi/src/streams
bufferedstream.h
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef STRIGI_BUFFEREDSTREAM_H
00021 #define STRIGI_BUFFEREDSTREAM_H
00022
00023 #include "streambase.h"
00024 #include "streambuffer.h"
00025 #include <cassert>
00026
00027 namespace Strigi {
00028
00036 template <class T>
00037 class BufferedStream : public StreamBase<T> {
00038 private:
00039 StreamBuffer<T> buffer;
00040 bool finishedWritingToBuffer;
00041
00042 void writeToBuffer(int32_t minsize, int32_t maxsize);
00043 protected:
00063 virtual int32_t fillBuffer(T* start, int32_t space) = 0;
00069 void resetBuffer() {
00070 StreamBase<T>::m_size = -1;
00071 StreamBase<T>::m_position = 0;
00072 StreamBase<T>::m_error.assign("");
00073 StreamBase<T>::m_status = Ok;
00074 buffer.readPos = buffer.start;
00075 buffer.avail = 0;
00076 finishedWritingToBuffer = false;
00077 }
00081 void setMinBufSize(int32_t s) {
00082 buffer.makeSpace(s);
00083 }
00084 BufferedStream<T>();
00085 public:
00086 int32_t read(const T*& start, int32_t min, int32_t max);
00087 int64_t reset(int64_t pos);
00088 virtual int64_t skip(int64_t ntoskip);
00089 };
00090
00091
00093 typedef BufferedStream<char> BufferedInputStream;
00094
00096 typedef BufferedStream<wchar_t> BufferedReader;
00097
00098
00099 template <class T>
00100 BufferedStream<T>::BufferedStream() {
00101 finishedWritingToBuffer = false;
00102 }
00103
00104 template <class T>
00105 void
00106 BufferedStream<T>::writeToBuffer(int32_t ntoread, int32_t maxread) {
00107 int32_t missing = ntoread - buffer.avail;
00108 int32_t nwritten = 0;
00109 while (missing > 0 && nwritten >= 0) {
00110 int32_t space;
00111 space = buffer.makeSpace(missing);
00112 if (maxread >= ntoread && space > maxread) {
00113 space = maxread;
00114 }
00115 T* start = buffer.readPos + buffer.avail;
00116 nwritten = fillBuffer(start, space);
00117 assert(StreamBase<T>::m_status != Eof);
00118 if (nwritten > 0) {
00119 buffer.avail += nwritten;
00120 missing = ntoread - buffer.avail;
00121 }
00122 }
00123 if (nwritten < 0) {
00124 finishedWritingToBuffer = true;
00125 }
00126 }
00127 template <class T>
00128 int32_t
00129 BufferedStream<T>::read(const T*& start, int32_t min, int32_t max) {
00130 if (StreamBase<T>::m_status == Error) return -2;
00131 if (StreamBase<T>::m_status == Eof) return -1;
00132
00133
00134 if (min > max) max = 0;
00135 if (!finishedWritingToBuffer && min > buffer.avail) {
00136
00137 writeToBuffer(min, max);
00138 if (StreamBase<T>::m_status == Error) return -2;
00139 }
00140
00141 int32_t nread = buffer.read(start, max);
00142
00143 StreamBase<T>::m_position += nread;
00144 if (StreamBase<T>::m_position > StreamBase<T>::m_size
00145 && StreamBase<T>::m_size > 0) {
00146
00147
00148
00149 StreamBase<T>::m_status = Error;
00150 StreamBase<T>::m_error = "Stream is longer than specified.";
00151 nread = -2;
00152 } else if (StreamBase<T>::m_status == Ok && buffer.avail == 0
00153 && finishedWritingToBuffer) {
00154 StreamBase<T>::m_status = Eof;
00155 if (StreamBase<T>::m_size == -1) {
00156 StreamBase<T>::m_size = StreamBase<T>::m_position;
00157 }
00158
00159 if (nread == 0) nread = -1;
00160 }
00161 return nread;
00162 }
00163 template <class T>
00164 int64_t
00165 BufferedStream<T>::reset(int64_t newpos) {
00166 assert(newpos >= 0);
00167 if (StreamBase<T>::m_status == Error) return -2;
00168
00169 int64_t d = StreamBase<T>::m_position - newpos;
00170 if (buffer.readPos - d >= buffer.start && -d < buffer.avail) {
00171 StreamBase<T>::m_position -= d;
00172 buffer.avail += (int32_t)d;
00173 buffer.readPos -= d;
00174 StreamBase<T>::m_status = Ok;
00175 }
00176 return StreamBase<T>::m_position;
00177 }
00178 template <class T>
00179 int64_t
00180 BufferedStream<T>::skip(int64_t ntoskip) {
00181 const T *begin;
00182 int32_t nread;
00183 int64_t skipped = 0;
00184 while (ntoskip) {
00185 int32_t step = (int32_t)((ntoskip > buffer.size) ?buffer.size :ntoskip);
00186 nread = read(begin, 1, step);
00187 if (nread <= 0) {
00188 return skipped;
00189 }
00190 ntoskip -= nread;
00191 skipped += nread;
00192 }
00193 return skipped;
00194 }
00195
00196 }
00197
00198 #endif