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