Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

wvstreamclone.cc

Go to the documentation of this file.
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, 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     // the sub-stream will force its own values, if it really wants.
00036     force_select(false, false, false);
00037 }
00038 
00039 
00040 WvStreamClone::~WvStreamClone()
00041 {
00042     //fprintf(stderr, "%p destroying: clone is %p\n", this, cloned);
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     //fprintf(stderr, "%p closing substream %p\n", this, cloned);
00057     if (cloned)
00058         cloned->setclosecallback(0, 0); // prevent recursion!
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     // we use cloned->read() here, not uread(), since we want the _clone_
00079     // to own the input buffer, not the main stream.
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     // we use cloned->write() here, not uwrite(), since we want the _clone_
00090     // to own the output buffer, not the main stream.
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             // si.wants |= cloned->force; // why would this be necessary?
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     // This currently always returns false, but we prolly should
00175     // still have it here in case it ever becomes useful
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             // si.wants |= cloned->force; // why would this be needed?
00189         }
00190 
00191         val = cloned->post_select(si);
00192         want_write = si.wants.writable;
00193         si.wants = oldwant;
00194         
00195         // return result if they're looking for writable and we still
00196         // have data in outbuf - the writable is for flushing, not for you!
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 }

Generated on Sat Mar 13 14:55:56 2004 for WvStreams by doxygen 1.3.6-20040222