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