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, void *)
00022 {
00023 if (!obj)
00024 obj = wvcreate<IWvStream>(s);
00025 return new WvStreamClone(mutate<IWvStream>(obj));
00026 }
00027
00028 static WvMoniker<IWvStream> reg("clone", creator);
00029
00030
00031 WvStreamClone::WvStreamClone(IWvStream *_cloned)
00032 : cloned(0), disassociate_on_close(false)
00033 {
00034 setclone(_cloned);
00035
00036 force_select(false, false, false);
00037 }
00038
00039
00040 WvStreamClone::~WvStreamClone()
00041 {
00042
00043 close();
00044 if (cloned)
00045 delete cloned;
00046 }
00047
00048 void WvStreamClone::nowrite()
00049 {
00050 if (cloned)
00051 cloned->nowrite();
00052 }
00053
00054 void WvStreamClone::close()
00055 {
00056
00057 if (cloned)
00058 cloned->setclosecallback(0, 0);
00059 WvStream::close();
00060 if (disassociate_on_close)
00061 cloned = NULL;
00062 if (cloned)
00063 cloned->close();
00064 }
00065
00066
00067 bool WvStreamClone::flush_internal(time_t msec_timeout)
00068 {
00069 if (cloned)
00070 return cloned->flush(msec_timeout);
00071 else
00072 return true;
00073 }
00074
00075
00076 size_t WvStreamClone::uread(void *buf, size_t size)
00077 {
00078
00079
00080 if (cloned)
00081 return cloned->read(buf, size);
00082 else
00083 return 0;
00084 }
00085
00086
00087 size_t WvStreamClone::uwrite(const void *buf, size_t size)
00088 {
00089
00090
00091 if (cloned)
00092 return cloned->write(buf, size);
00093 else
00094 return 0;
00095 }
00096
00097
00098 bool WvStreamClone::isok() const
00099 {
00100 if (errnum)
00101 return false;
00102 if (cloned)
00103 return cloned->isok();
00104 return false;
00105 }
00106
00107
00108 int WvStreamClone::geterr() const
00109 {
00110 if (errnum)
00111 return errnum;
00112 if (cloned)
00113 return cloned->geterr();
00114 return EIO;
00115 }
00116
00117
00118 WvString WvStreamClone::errstr() const
00119 {
00120 if (errnum)
00121 return WvStream::errstr();
00122 if (cloned)
00123 return cloned->errstr();
00124 return "No child stream!";
00125 }
00126
00127
00128 static void close_callback(WvStream &s, void *userdata)
00129 {
00130 WvStreamClone *_this = (WvStreamClone *)userdata;
00131 if (_this->cloned == &s)
00132 _this->close();
00133 }
00134
00135
00136 void WvStreamClone::setclone(IWvStream *newclone)
00137 {
00138 if (cloned)
00139 cloned->setclosecallback(0, 0);
00140 cloned = newclone;
00141 if (cloned)
00142 cloned->setclosecallback(close_callback, this);
00143 }
00144
00145
00146 bool WvStreamClone::pre_select(SelectInfo &si)
00147 {
00148 SelectRequest oldwant;
00149 bool result = WvStream::pre_select(si);
00150 if (cloned && cloned->isok())
00151 {
00152 oldwant = si.wants;
00153
00154 if (!si.inherit_request)
00155 {
00156 si.wants |= force;
00157
00158 }
00159
00160 if (outbuf.used() || autoclose_time)
00161 si.wants.writable = true;
00162
00163 result = result || cloned->pre_select(si);
00164
00165 si.wants = oldwant;
00166 }
00167 return result;
00168 }
00169
00170
00171 bool WvStreamClone::post_select(SelectInfo &si)
00172 {
00173 SelectRequest oldwant;
00174
00175
00176 bool result = WvStream::post_select(si);
00177 bool val, want_write;
00178
00179 if (cloned && cloned->should_flush())
00180 flush(0);
00181
00182 if (cloned && cloned->isok())
00183 {
00184 oldwant = si.wants;
00185 if (!si.inherit_request)
00186 {
00187 si.wants |= force;
00188
00189 }
00190
00191 val = cloned->post_select(si);
00192 want_write = si.wants.writable;
00193 si.wants = oldwant;
00194
00195
00196
00197 if (want_write && outbuf.used())
00198 return result;
00199 else if (val && si.wants.readable && read_requires_writable
00200 && !read_requires_writable->select(0, false, true))
00201 return result;
00202 else if (val && si.wants.writable && write_requires_readable
00203 && !write_requires_readable->select(0, true, false))
00204 return result;
00205 else
00206 return val || result;
00207 }
00208
00209 return result;
00210 }
00211
00212
00213 const WvAddr *WvStreamClone::src() const
00214 {
00215 if (cloned)
00216 return cloned->src();
00217 return NULL;
00218 }
00219
00220
00221 void WvStreamClone::execute()
00222 {
00223 WvStream::execute();
00224 if (cloned) cloned->callback();
00225 }