00001
00002
00003
00004
00005
00006
00007
00008
00009 #include "wvencoderstream.h"
00010
00011 WvEncoderStream::WvEncoderStream(WvStream *_cloned) : WvStreamClone(_cloned)
00012 {
00013 is_closing = false;
00014 is_eof = false;
00015 min_readsize = 0;
00016 }
00017
00018
00019 WvEncoderStream::~WvEncoderStream()
00020 {
00021 close();
00022 }
00023
00024
00025 void WvEncoderStream::close()
00026 {
00027
00028
00029
00030
00031 if (is_closing) return;
00032 is_closing = true;
00033
00034
00035 finish_read();
00036 finish_write();
00037
00038 WvStreamClone::close();
00039 }
00040
00041
00042 bool WvEncoderStream::isok() const
00043 {
00044
00045 if (! WvStream::isok())
00046 return false;
00047
00048
00049
00050
00051 if (! cloned || cloned->geterr() != 0)
00052 return false;
00053
00054
00055 return ! is_eof;
00056 }
00057
00058
00059 bool WvEncoderStream::flush_internal(time_t msec_timeout)
00060 {
00061 flush_write();
00062
00063
00064 while (isok() && writeoutbuf.used())
00065 {
00066 WvEncoderStream::flush(msec_timeout);
00067 if (!msec_timeout || !select(msec_timeout, false, true))
00068 {
00069 if (msec_timeout >= 0)
00070 break;
00071 }
00072 }
00073
00074 return !writeoutbuf.used();
00075 }
00076
00077
00078 bool WvEncoderStream::flush_read()
00079 {
00080 bool success = readchain.flush(readinbuf, readoutbuf);
00081 checkreadisok();
00082 inbuf.merge(readoutbuf);
00083 return success;
00084 }
00085
00086
00087 bool WvEncoderStream::flush_write()
00088 {
00089 bool success = push(true , false );
00090 return success;
00091 }
00092
00093
00094 bool WvEncoderStream::finish_read()
00095 {
00096 bool success = readchain.flush(readinbuf, readoutbuf);
00097 if (! readchain.finish(readoutbuf))
00098 success = false;
00099 checkreadisok();
00100 inbuf.merge(readoutbuf);
00101 is_eof = true;
00102 return success;
00103 }
00104
00105
00106 bool WvEncoderStream::finish_write()
00107 {
00108 return push(true , true );
00109 }
00110
00111
00112 void WvEncoderStream::pull(size_t size)
00113 {
00114 if (is_eof)
00115 return;
00116
00117
00118 bool finish = false;
00119 if (! readchain.isfinished() && cloned)
00120 {
00121 if (size != 0)
00122 cloned->read(readinbuf, size);
00123 if (! cloned->isok())
00124 finish = true;
00125 }
00126
00127
00128 readchain.encode(readinbuf, readoutbuf, finish );
00129 if (finish)
00130 {
00131 readchain.finish(readoutbuf);
00132 if (readoutbuf.used() == 0 && inbuf.used() == 0)
00133 is_eof = true;
00134
00135 }
00136 else if (readoutbuf.used() == 0 && inbuf.used() == 0 && readchain.isfinished())
00137 {
00138
00139
00140 is_eof = true;
00141 }
00142 checkreadisok();
00143 }
00144
00145
00146 bool WvEncoderStream::push(bool flush, bool finish)
00147 {
00148
00149 if (flush)
00150 writeinbuf.merge(outbuf);
00151 bool success = writechain.encode(writeinbuf, writeoutbuf, flush);
00152 if (finish)
00153 if (! writechain.finish(writeoutbuf))
00154 success = false;
00155 checkwriteisok();
00156
00157
00158 size_t size = writeoutbuf.used();
00159 if (size != 0)
00160 {
00161 const unsigned char *writeout = writeoutbuf.get(size);
00162 size_t len = WvStreamClone::uwrite(writeout, size);
00163 writeoutbuf.unget(size - len);
00164 }
00165 return success;
00166 }
00167
00168
00169 size_t WvEncoderStream::uread(void *buf, size_t size)
00170 {
00171 if (size && readoutbuf.used() == 0)
00172 {
00173 pull(min_readsize > size ? min_readsize : size);
00174 }
00175 size_t avail = readoutbuf.used();
00176 if (size > avail)
00177 size = avail;
00178 readoutbuf.move(buf, size);
00179 return size;
00180 }
00181
00182
00183 size_t WvEncoderStream::uwrite(const void *buf, size_t size)
00184 {
00185 writeinbuf.put(buf, size);
00186 push(false , false );
00187 return size;
00188 }
00189
00190
00191 bool WvEncoderStream::pre_select(SelectInfo &si)
00192 {
00193 bool surething = false;
00194
00195
00196
00197
00198 if (si.wants.readable)
00199 {
00200 pull(0);
00201 if (readoutbuf.used() != 0)
00202 surething = true;
00203 }
00204
00205
00206
00207 push(false , false );
00208
00209
00210 if (WvStreamClone::pre_select(si))
00211 surething = true;
00212 return surething;
00213 }
00214
00215
00216 void WvEncoderStream::checkreadisok()
00217 {
00218 if (! readchain.isok())
00219 {
00220 seterr(WvString("read chain: %s", readchain.geterror()));
00221 is_eof = true;
00222 }
00223 }
00224
00225
00226 void WvEncoderStream::checkwriteisok()
00227 {
00228 if (! writechain.isok())
00229 seterr(WvString("write chain: %s", writechain.geterror()));
00230 }