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