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

wvencoderstream.cc

Go to the documentation of this file.
00001 /* 00002 * Worldvisions Tunnel Vision Software: 00003 * Copyright (C) 1997-2002 Net Integration Technologies, Inc. 00004 * 00005 * WvEncoderStream chains a series of encoders on the input and 00006 * output ports of the underlying stream to effect on-the-fly data 00007 * transformations. 00008 */ 00009 #include "wvencoderstream.h" 00010 00011 WvEncoderStream::WvEncoderStream(WvStream *_cloned) : WvStreamClone(_cloned) 00012 { 00013 is_closing = false; 00014 is_eof = false; 00015 min_readsize = 0; 00016 } 00017 00018 00019 WvEncoderStream::~WvEncoderStream() 00020 { 00021 close(); 00022 } 00023 00024 00025 void WvEncoderStream::close() 00026 { 00027 // we want to finish the encoders even if !isok() since we 00028 // might just have encountered an EOF condition, and we want 00029 // to ensure that the remaining data is processed, but this 00030 // might cause recursion if the encoders set a new error condition 00031 if (is_closing) return; 00032 is_closing = true; 00033 00034 // finish encoders 00035 finish_read(); 00036 finish_write(); 00037 // flush write chain and close the stream 00038 WvStreamClone::close(); 00039 } 00040 00041 00042 bool WvEncoderStream::isok() const 00043 { 00044 // handle encoder error conditions 00045 if (! WvStream::isok()) 00046 return false; 00047 00048 // handle substream error conditions 00049 // we don't check substream isok() because that is handled 00050 // during read operations to distinguish EOF from errors 00051 if (! cloned || cloned->geterr() != 0) 00052 return false; 00053 00054 // handle deferred EOF condition 00055 return ! is_eof; 00056 } 00057 00058 00059 bool WvEncoderStream::flush_internal(time_t msec_timeout) 00060 { 00061 flush_write(); 00062 00063 // flush underlying stream 00064 while (isok() && writeoutbuf.used()) 00065 { 00066 WvEncoderStream::flush(msec_timeout); 00067 if (!msec_timeout || !select(msec_timeout, false, true)) 00068 { 00069 if (msec_timeout >= 0) 00070 break; 00071 } 00072 } 00073 00074 return !writeoutbuf.used(); 00075 } 00076 00077 00078 bool WvEncoderStream::flush_read() 00079 { 00080 bool success = readchain.flush(readinbuf, readoutbuf); 00081 checkreadisok(); 00082 inbuf.merge(readoutbuf); 00083 return success; 00084 } 00085 00086 00087 bool WvEncoderStream::flush_write() 00088 { 00089 bool success = push(true /*flush*/, false /*finish*/); 00090 return success; 00091 } 00092 00093 00094 bool WvEncoderStream::finish_read() 00095 { 00096 bool success = readchain.flush(readinbuf, readoutbuf); 00097 if (! readchain.finish(readoutbuf)) 00098 success = false; 00099 checkreadisok(); 00100 inbuf.merge(readoutbuf); 00101 is_eof = true; 00102 return success; 00103 } 00104 00105 00106 bool WvEncoderStream::finish_write() 00107 { 00108 return push(true /*flush*/, true /*finish*/); 00109 } 00110 00111 00112 void WvEncoderStream::pull(size_t size) 00113 { 00114 if (is_eof) 00115 return; 00116 00117 // pull a chunk of unencoded input 00118 bool finish = false; 00119 if (! readchain.isfinished() && cloned) 00120 { 00121 if (size != 0) 00122 cloned->read(readinbuf, size); 00123 if (! cloned->isok()) 00124 finish = true; // underlying stream hit EOF or error 00125 } 00126 00127 // encode the input 00128 readchain.encode(readinbuf, readoutbuf, finish /* flush*/); 00129 if (finish) 00130 { 00131 readchain.finish(readoutbuf); 00132 if (readoutbuf.used() == 0 && inbuf.used() == 0) 00133 is_eof = true; 00134 // otherwise defer EOF until the buffered data has been read 00135 } 00136 else if (readoutbuf.used() == 0 && inbuf.used() == 0 && readchain.isfinished()) 00137 { 00138 // only get EOF when the chain is finished and we have no 00139 // more data 00140 is_eof = true; 00141 } 00142 checkreadisok(); 00143 } 00144 00145 00146 bool WvEncoderStream::push(bool flush, bool finish) 00147 { 00148 // encode the output 00149 if (flush) 00150 writeinbuf.merge(outbuf); 00151 bool success = writechain.encode(writeinbuf, writeoutbuf, flush); 00152 if (finish) 00153 if (! writechain.finish(writeoutbuf)) 00154 success = false; 00155 checkwriteisok(); 00156 00157 // push encoded output to cloned stream 00158 size_t size = writeoutbuf.used(); 00159 if (size != 0) 00160 { 00161 const unsigned char *writeout = writeoutbuf.get(size); 00162 size_t len = WvStreamClone::uwrite(writeout, size); 00163 writeoutbuf.unget(size - len); 00164 } 00165 return success; 00166 } 00167 00168 00169 size_t WvEncoderStream::uread(void *buf, size_t size) 00170 { 00171 if (size && readoutbuf.used() == 0) 00172 { 00173 pull(min_readsize > size ? min_readsize : size); 00174 } 00175 size_t avail = readoutbuf.used(); 00176 if (size > avail) 00177 size = avail; 00178 readoutbuf.move(buf, size); 00179 return size; 00180 } 00181 00182 00183 size_t WvEncoderStream::uwrite(const void *buf, size_t size) 00184 { 00185 writeinbuf.put(buf, size); 00186 push(false /*flush*/, false /*finish*/); 00187 return size; 00188 } 00189 00190 00191 bool WvEncoderStream::pre_select(SelectInfo &si) 00192 { 00193 bool surething = false; 00194 00195 // if we have buffered input data and we want to check for 00196 // readability, then cause a callback to occur that will 00197 // hopefully ask us for more data via uread() 00198 if (si.wants.readable) 00199 { 00200 pull(0); // try an encode 00201 if (readoutbuf.used() != 0) 00202 surething = true; 00203 } 00204 00205 // try to push pending encoded output to cloned stream 00206 // outbuf_delayed_flush condition already handled by uwrite() 00207 push(false /*flush*/, false /*finish*/); 00208 00209 // consult the underlying stream 00210 if (WvStreamClone::pre_select(si)) 00211 surething = true; 00212 return surething; 00213 } 00214 00215 00216 void WvEncoderStream::checkreadisok() 00217 { 00218 if (! readchain.isok()) 00219 { 00220 seterr(WvString("read chain: %s", readchain.geterror())); 00221 is_eof = true; 00222 } 00223 } 00224 00225 00226 void WvEncoderStream::checkwriteisok() 00227 { 00228 if (! writechain.isok()) 00229 seterr(WvString("write chain: %s", writechain.geterror())); 00230 }

Generated on Tue Oct 5 01:09:20 2004 for WvStreams by doxygen 1.3.7