wvstreamclone.cc

00001 /*
00002  * Worldvisions Weaver Software:
00003  *   Copyright (C) 1997-2002 Net Integration Technologies, Inc.
00004  * 
00005  * WvStreamClone simply forwards all requests to the "cloned" stream.
00006  * 
00007  * NOTE: this file is a pain to maintain, because many of these functions
00008  * are almost (but not quite) exactly like the ones in WvStream.  If
00009  * WvStream changes, you need to change this too.
00010  * 
00011  * See wvstreamclone.h.
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     // the sub-stream will force its own values, if it really wants.
00034     force_select(false, false, false);
00035 }
00036 
00037 
00038 WvStreamClone::~WvStreamClone()
00039 {
00040     //fprintf(stderr, "%p destroying: clone is %p\n", this, cloned);
00041     close();
00042     WVRELEASE(cloned);
00043 }
00044 
00045 
00046 void WvStreamClone::noread()
00047 {
00048     // unlike nowrite(), it is safe to call cloned->noread() immediately.
00049     // That will pass the shutdown(SHUT_RD) on to the deepest stream right
00050     // away, but won't close anything until all the inbufs are empty.
00051     if (cloned)
00052         cloned->noread();
00053     WvStream::noread();
00054 }
00055 
00056 
00057 void WvStreamClone::nowrite()
00058 {
00059     // this sets stop_write.  We call cloned->nowrite() in flush_internal()
00060     // when our outbuf is flushed (because until then, we *do* want to be
00061     // able to write to the clone).
00062     if (cloned && !outbuf.used())
00063         cloned->nowrite();
00064     WvStream::nowrite();
00065 }
00066 
00067 
00068 void WvStreamClone::close()
00069 {
00070     // fprintf(stderr, "%p closing substream %p\n", this, cloned);
00071     if (cloned)
00072         cloned->setclosecallback(0); // prevent recursion!
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     // we use cloned->read() here, not uread(), since we want the _clone_
00097     // to own the input buffer, not the main stream.
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     // we use cloned->write() here, not uwrite(), since we want the _clone_
00115     // to own the output buffer, not the main stream.
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     // don't do this: cloned's closecallback will close us when needed.
00132     // return cloned->isok();
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         //fprintf(stderr, "streamclone-closecb: %d/%d/%d/%d/%d\n",
00161         //      stop_read, stop_write, outbuf.used(), inbuf.used(), closed);
00162         nowrite();
00163         noread();
00164         // close();
00165         //fprintf(stderr, "streamclone-closecb2: %d/%d/%d/%d/%d\n",
00166         //      stop_read, stop_write, outbuf.used(), inbuf.used(), closed);
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             // si.wants |= cloned->force; // why would this be necessary?
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     // This currently always returns false, but we prolly should
00215     // still have it here in case it ever becomes useful
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             // si.wants |= cloned->force; // why would this be needed?
00231         }
00232 
00233         val = cloned->post_select(si);
00234         want_write = si.wants.writable;
00235         si.wants = oldwant;
00236         
00237         // return result if they're looking for writable and we still
00238         // have data in outbuf - the writable is for flushing, not for you!
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 }

Generated on Thu May 25 21:51:04 2006 for WvStreams by  doxygen 1.4.6