00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include "wvstreamclone.h"
00014 #include "wvmoniker.h"
00015
00016 #ifdef _MSC_VER
00017 #pragma warning(disable : 4073)
00018 #pragma init_seg(lib)
00019 #endif
00020
00021 static IWvStream *creator(WvStringParm s)
00022 {
00023 return new WvStreamClone(wvcreate<IWvStream>(s));
00024 }
00025
00026 static WvMoniker<IWvStream> reg("clone", creator);
00027
00028
00029 WvStreamClone::WvStreamClone(IWvStream *_cloned)
00030 : cloned(0),
00031 disassociate_on_close(false),
00032 my_type("WvStreamClone:(none)")
00033 {
00034 setclone(_cloned);
00035
00036 force_select(false, false, false);
00037 }
00038
00039
00040 WvStreamClone::~WvStreamClone()
00041 {
00042
00043 close();
00044 WVRELEASE(cloned);
00045 }
00046
00047
00048 void WvStreamClone::noread()
00049 {
00050
00051
00052
00053 if (cloned)
00054 cloned->noread();
00055 WvStream::noread();
00056 }
00057
00058
00059 void WvStreamClone::nowrite()
00060 {
00061
00062
00063
00064 if (cloned && !outbuf.used())
00065 cloned->nowrite();
00066 WvStream::nowrite();
00067 }
00068
00069
00070 void WvStreamClone::close()
00071 {
00072
00073 if (cloned)
00074 cloned->setclosecallback(0);
00075 WvStream::close();
00076 if (disassociate_on_close)
00077 setclone(NULL);
00078 if (cloned)
00079 cloned->close();
00080 }
00081
00082
00083 bool WvStreamClone::flush_internal(time_t msec_timeout)
00084 {
00085 if (cloned)
00086 {
00087 if (stop_write && !outbuf.used())
00088 cloned->nowrite();
00089 return cloned->flush(msec_timeout);
00090 }
00091 else
00092 return true;
00093 }
00094
00095
00096 size_t WvStreamClone::uread(void *buf, size_t size)
00097 {
00098
00099
00100 if (cloned)
00101 {
00102 size_t len = 0;
00103 if (cloned->isok())
00104 len = cloned->read(buf, size);
00105 if (len == 0 && !cloned->isok())
00106 close();
00107 return len;
00108 }
00109 else
00110 return 0;
00111 }
00112
00113
00114 size_t WvStreamClone::uwrite(const void *buf, size_t size)
00115 {
00116
00117
00118 if (cloned)
00119 return cloned->write(buf, size);
00120 else
00121 return 0;
00122 }
00123
00124
00125 bool WvStreamClone::isok() const
00126 {
00127 if (geterr())
00128 return false;
00129 if (!cloned)
00130 return false;
00131 return WvStream::isok();
00132
00133
00134
00135 }
00136
00137
00138 int WvStreamClone::geterr() const
00139 {
00140 if (WvStream::geterr())
00141 return WvStream::geterr();
00142 if (cloned)
00143 return cloned->geterr();
00144 return EIO;
00145 }
00146
00147
00148 WvString WvStreamClone::errstr() const
00149 {
00150 if (WvStream::geterr())
00151 return WvStream::errstr();
00152 if (cloned)
00153 return cloned->errstr();
00154 return "No child stream!";
00155 }
00156
00157
00158 void WvStreamClone::close_callback(WvStream &s)
00159 {
00160 if (cloned == &s)
00161 {
00162
00163
00164 nowrite();
00165 noread();
00166
00167
00168
00169 }
00170 }
00171
00172
00173 void WvStreamClone::setclone(IWvStream *newclone)
00174 {
00175 if (cloned)
00176 cloned->setclosecallback(0);
00177 cloned = newclone;
00178 closed = stop_read = stop_write = false;
00179 if (cloned)
00180 cloned->setclosecallback(IWvStreamCallback(this, &WvStreamClone::close_callback));
00181
00182 if (newclone != NULL)
00183 my_type = WvString("WvStreamClone:%s", newclone->wstype());
00184 else
00185 my_type = "WvStreamClone:(none)";
00186 }
00187
00188
00189 void WvStreamClone::pre_select(SelectInfo &si)
00190 {
00191 SelectRequest oldwant = si.wants;
00192 WvStream::pre_select(si);
00193
00194 if (cloned && cloned->isok())
00195 {
00196 if (!si.inherit_request)
00197 {
00198 si.wants.readable |= readcb;
00199 si.wants.writable |= writecb;
00200 si.wants.isexception |= exceptcb;
00201 }
00202
00203 if (outbuf.used() || autoclose_time)
00204 si.wants.writable = true;
00205
00206 cloned->pre_select(si);
00207 si.wants = oldwant;
00208 }
00209 }
00210
00211
00212 bool WvStreamClone::post_select(SelectInfo &si)
00213 {
00214 SelectRequest oldwant = si.wants;
00215
00216
00217 bool result = WvStream::post_select(si);
00218 bool val, want_write;
00219
00220 if (cloned && cloned->should_flush())
00221 flush(0);
00222
00223 if (cloned && cloned->isok())
00224 {
00225 if (!si.inherit_request)
00226 {
00227 si.wants.readable |= readcb;
00228 si.wants.writable |= writecb;
00229 si.wants.isexception |= exceptcb;
00230 }
00231
00232 val = cloned->post_select(si);
00233 want_write = si.wants.writable;
00234 si.wants = oldwant;
00235
00236
00237
00238 if (want_write && outbuf.used())
00239 return result;
00240 else if (val && si.wants.readable && read_requires_writable
00241 && !read_requires_writable->select(0, false, true))
00242 return result;
00243 else if (val && si.wants.writable && write_requires_readable
00244 && !write_requires_readable->select(0, true, false))
00245 return result;
00246 else
00247 return val || result;
00248 }
00249
00250 return result;
00251 }
00252
00253
00254 const WvAddr *WvStreamClone::src() const
00255 {
00256 if (cloned)
00257 return cloned->src();
00258 return NULL;
00259 }
00260
00261
00262 void WvStreamClone::execute()
00263 {
00264 WvStream::execute();
00265 if (cloned) cloned->callback();
00266 }