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 Sat Feb 21 21:05:27 2004 for WvStreams by doxygen 1.3.5