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 Tue Oct 5 01:09:21 2004 for WvStreams by doxygen 1.3.7