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

wvencoder.cc

Go to the documentation of this file.
00001 /*
00002  * Worldvisions Weaver Software:
00003  *   Copyright (C) 1997-2002 Net Integration Technologies, Inc.
00004  * 
00005  * A top-level data encoder class.  See wvencoder.h.
00006  */
00007 #include "wvencoder.h"
00008 
00009 /***** WvEncoder *****/
00010 
00011 WvEncoder::WvEncoder() : okay(true), finished(false)
00012 {
00013 }
00014 
00015 
00016 WvEncoder::~WvEncoder()
00017 {
00018 }
00019 
00020 
00021 WvString WvEncoder::geterror() const
00022 {
00023     if (isok())
00024         return WvString::null;
00025     if (!! errstr)
00026         return errstr;
00027     WvString message = _geterror();
00028     if (!! message)
00029         return message;
00030     return "unknown encoder error";
00031 }
00032 
00033 
00034 bool WvEncoder::encode(WvBuf &inbuf, WvBuf &outbuf,
00035     bool flush, bool _finish)
00036 {
00037     // deliberately not using isok() and isfinished() here
00038     bool success = okay && ! finished && (inbuf.used() != 0 || flush);
00039     if (success)
00040         success = _encode(inbuf, outbuf, flush);
00041     if (_finish)
00042         success = finish(outbuf) && success;
00043     return success;
00044 }
00045 
00046 
00047 bool WvEncoder::finish(WvBuf &outbuf)
00048 {
00049     // deliberately not using isok() and isfinished() here
00050     bool success = okay && ! finished;
00051     if (success)
00052         success = _finish(outbuf);
00053     setfinished();
00054     return success;
00055 }
00056 
00057 
00058 bool WvEncoder::reset()
00059 {
00060     // reset local state
00061     okay = true;
00062     finished = false;
00063     errstr = WvString::null;
00064     // attempt to reset the encoder
00065     bool success = _reset();
00066     if (! success)
00067     {
00068         if (okay)
00069             seterror("reset not supported by encoder");
00070     }
00071     return success;
00072 }
00073 
00074 
00075 bool WvEncoder::flushstrbuf(WvStringParm instr, WvBuf &outbuf,
00076     bool finish)
00077 {
00078     WvConstStringBuffer inbuf(instr);
00079     bool success = encode(inbuf, outbuf, true, finish);
00080     return success;
00081 }
00082 
00083 
00084 bool WvEncoder::flushstrstr(WvStringParm instr, WvString &outstr,
00085     bool finish)
00086 {
00087     WvConstStringBuffer inbuf(instr);
00088     WvDynBuf outbuf;
00089     bool success = encode(inbuf, outbuf, true, finish);
00090     outstr.append(outbuf.getstr());
00091     return success;
00092 }
00093 
00094 
00095 bool WvEncoder::encodebufstr(WvBuf &inbuf, WvString &outstr,
00096     bool flush, bool finish)
00097 {
00098     WvDynBuf outbuf;
00099     bool success = encode(inbuf, outbuf, flush, finish);
00100     outstr.append(outbuf.getstr());
00101     return success;
00102 }
00103 
00104 
00105 WvString WvEncoder::strflushstr(WvStringParm instr, bool finish)
00106 {
00107     WvString outstr;
00108     flushstrstr(instr, outstr, finish);
00109     return outstr;
00110 }
00111 
00112 
00113 WvString WvEncoder::strflushbuf(WvBuf &inbuf, bool finish)
00114 {
00115     WvString outstr;
00116     flushbufstr(inbuf, outstr, finish);
00117     return outstr;
00118 }
00119 
00120 
00121 bool WvEncoder::flushmembuf(const void *inmem, size_t inlen,
00122     WvBuf &outbuf, bool finish)
00123 {
00124     WvConstInPlaceBuf inbuf(inmem, inlen);
00125     bool success = encode(inbuf, outbuf, true, finish);
00126     return success;
00127 }
00128 
00129 
00130 bool WvEncoder::flushmemmem(const void *inmem, size_t inlen,
00131     void *outmem, size_t *outlen, bool finish)
00132 {
00133     WvConstInPlaceBuf inbuf(inmem, inlen);
00134     return encodebufmem(inbuf, outmem, outlen, true, finish);
00135 }
00136 
00137 
00138 bool WvEncoder::encodebufmem(WvBuf &inbuf,
00139     void *outmem, size_t *outlen, bool flush, bool finish)
00140 {
00141     WvInPlaceBuf outbuf(outmem, 0, *outlen);
00142     bool success = encode(inbuf, outbuf, true, finish);
00143     *outlen = outbuf.used();
00144     return success;
00145 }
00146 
00147 
00148 bool WvEncoder::flushstrmem(WvStringParm instr,
00149     void *outmem, size_t *outlen, bool finish)
00150 {
00151     WvConstStringBuffer inbuf(instr);
00152     return flushbufmem(inbuf, outmem, outlen, finish);
00153 }
00154 
00155 
00156 WvString WvEncoder::strflushmem(const void *inmem, size_t inlen, bool finish)
00157 {
00158     WvConstInPlaceBuf inbuf(inmem, inlen);
00159     return strflushbuf(inbuf, finish);
00160 }
00161 
00162 
00163 /***** WvNullEncoder *****/
00164 
00165 bool WvNullEncoder::_encode(WvBuf &in, WvBuf &out, bool flush)
00166 {
00167     in.zap();
00168     return true;
00169 }
00170 
00171 
00172 bool WvNullEncoder::_reset()
00173 {
00174     return true;
00175 }
00176 
00177 
00178 
00179 /***** WvPassthroughEncoder *****/
00180 
00181 WvPassthroughEncoder::WvPassthroughEncoder()
00182 {
00183     _reset();
00184 }
00185 
00186 
00187 bool WvPassthroughEncoder::_encode(WvBuf &in, WvBuf &out, bool flush)
00188 {
00189     total += in.used();
00190     out.merge(in);
00191     return true;
00192 }
00193 
00194 
00195 bool WvPassthroughEncoder::_reset()
00196 {
00197     total = 0;
00198     return true;
00199 }
00200 
00201 
00202 
00203 /***** WvEncoderChain *****/
00204 
00205 WvEncoderChain::WvEncoderChain()
00206 {
00207 }
00208 
00209 
00210 WvEncoderChain::~WvEncoderChain()
00211 {
00212 }
00213 
00214 
00215 bool WvEncoderChain::_isok() const
00216 {
00217     WvEncoderChainElemListBase::Iter it(
00218         const_cast<WvEncoderChainElemListBase&>(encoders));
00219     for (it.rewind(); it.next(); )
00220     {
00221         WvEncoderChainElem *encelem = it.ptr();
00222         if (! encelem->enc->isok())
00223             return false;
00224     }
00225     return true;
00226 }
00227 
00228 
00229 bool WvEncoderChain::_isfinished() const
00230 {
00231     WvEncoderChainElemListBase::Iter it(
00232         const_cast<WvEncoderChainElemListBase&>(encoders));
00233     for (it.rewind(); it.next(); )
00234     {
00235         WvEncoderChainElem *encelem = it.ptr();
00236         if (encelem->enc->isfinished())
00237             return true;
00238     }
00239     return false;
00240 }
00241 
00242 
00243 WvString WvEncoderChain::_geterror() const
00244 {
00245     WvEncoderChainElemListBase::Iter it(
00246         const_cast<WvEncoderChainElemListBase&>(encoders));
00247     for (it.rewind(); it.next(); )
00248     {
00249         WvEncoderChainElem *encelem = it.ptr();
00250         WvString message = encelem->enc->geterror();
00251         if (!! message)
00252             return message;
00253     }
00254     return WvString::null;
00255 }
00256 
00257 
00258 // NOTE: In this function we deliberately ignore deep isok() and
00259 //       isfinished() results to allow addition/removal of
00260 //       individual broken encoders while still processing data
00261 //       through as much of the chain as possible.
00262 bool WvEncoderChain::_encode(WvBuf &in, WvBuf &out, bool flush)
00263 {
00264     if (encoders.isempty())
00265         return passthrough.encode(in, out, flush);
00266 
00267     // iterate over all encoders in the list
00268     bool success = true;
00269     WvEncoderChainElemListBase::Iter it(encoders);
00270     it.rewind();
00271     it.next();
00272     for (WvBuf *tmpin = & in;;)
00273     {
00274         // merge pending output and select an output buffer
00275         WvEncoderChainElem *encelem = it.ptr();
00276         bool hasnext = it.next();
00277         WvBuf *tmpout;
00278         if (! hasnext)
00279         {
00280             out.merge(encelem->out);
00281             tmpout = & out;
00282         }
00283         else
00284             tmpout = & encelem->out;
00285 
00286         // encode
00287         if (! encelem->enc->encode(*tmpin, *tmpout, flush))
00288             success = false;
00289 
00290         if (! hasnext)
00291             break;
00292         tmpin = & encelem->out;
00293     }
00294     return success;
00295 }
00296 
00297 
00298 // NOTE: In this function we deliberately ignore deep isok() and
00299 //       isfinished() results to allow addition/removal of
00300 //       individual broken encoders while still processing data
00301 //       through as much of the chain as possible.
00302 bool WvEncoderChain::_finish(WvBuf &out)
00303 {
00304     if (encoders.isempty())
00305         return true;
00306     
00307     // iterate over all encoders in the list
00308     bool success = true;
00309     WvEncoderChainElemListBase::Iter it(encoders);
00310     it.rewind();
00311     it.next();
00312     bool needs_flush = false;
00313     for (WvBuf *tmpin = NULL;;)
00314     {
00315         // merge pending output and select an output buffer
00316         WvEncoderChainElem *encelem = it.ptr();
00317         bool hasnext = it.next();
00318         WvBuf *tmpout;
00319         if (! hasnext)
00320         {
00321             out.merge(encelem->out);
00322             tmpout = & out;
00323         }
00324         else
00325             tmpout = & encelem->out;
00326 
00327         // do we need to flush first due to new input?
00328         size_t oldused = tmpout->used();
00329         if (needs_flush)
00330         {
00331             if (! encelem->enc->flush(*tmpin, *tmpout))
00332                 success = false;
00333             needs_flush = true;
00334         }
00335         
00336         // tell the encoder to finish
00337         if (! encelem->enc->finish(*tmpout))
00338             success = false;
00339             
00340         // check whether any new data was generated
00341         if (oldused != tmpout->used())
00342             needs_flush = true;
00343 
00344         if (! hasnext)
00345             break;
00346         tmpin = & encelem->out;
00347     }
00348     return success;
00349 }
00350 
00351 
00352 bool WvEncoderChain::_reset()
00353 {
00354     bool success = true;
00355     WvEncoderChainElemListBase::Iter it(encoders);
00356     for (it.rewind(); it.next(); )
00357     {
00358         WvEncoderChainElem *encelem = it.ptr();
00359         encelem->out.zap();
00360         if (! encelem->enc->reset())
00361             success = false;
00362     }
00363     return success;
00364 }
00365 
00366 
00367 void WvEncoderChain::append(WvEncoder *enc, bool auto_free)
00368 {
00369     encoders.append(new WvEncoderChainElem(enc, auto_free), true);
00370 }
00371 
00372 
00373 void WvEncoderChain::prepend(WvEncoder *enc, bool auto_free)
00374 {
00375     encoders.prepend(new WvEncoderChainElem(enc, auto_free), true);
00376 }
00377 
00378 
00379 void WvEncoderChain::unlink(WvEncoder *enc)
00380 {
00381     WvEncoderChainElemListBase::Iter it(encoders);
00382     for (it.rewind(); it.next(); )
00383     {
00384         WvEncoderChainElem *encelem = it.ptr();
00385         if (encelem->enc == enc)
00386             it.xunlink();
00387     }
00388 }
00389 
00390 void WvEncoderChain::zap()
00391 {
00392     encoders.zap();
00393 }

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