Logo Search packages:      
Sourcecode: wvstreams version File versions

wvencoder.cc

/*
 * Worldvisions Weaver Software:
 *   Copyright (C) 1997-2002 Net Integration Technologies, Inc.
 * 
 * A top-level data encoder class.  See wvencoder.h.
 */
#include "wvencoder.h"

/***** WvEncoder *****/

00011 WvEncoder::WvEncoder() : okay(true), finished(false)
{
}


00016 WvEncoder::~WvEncoder()
{
}


00021 WvString WvEncoder::geterror() const
{
    if (isok())
        return WvString::null;
    if (!! errstr)
        return errstr;
    WvString message = _geterror();
    if (!! message)
        return message;
    return "unknown encoder error";
}


00034 bool WvEncoder::encode(WvBuf &inbuf, WvBuf &outbuf,
    bool flush, bool _finish)
{
    // deliberately not using isok() and isfinished() here
    bool success = okay && ! finished && (inbuf.used() != 0 || flush);
    if (success)
        success = _encode(inbuf, outbuf, flush);
    if (_finish)
        success = finish(outbuf) && success;
    return success;
}


00047 bool WvEncoder::finish(WvBuf &outbuf)
{
    // deliberately not using isok() and isfinished() here
    bool success = okay && ! finished;
    if (success)
        success = _finish(outbuf);
    setfinished();
    return success;
}


00058 bool WvEncoder::reset()
{
    // reset local state
    okay = true;
    finished = false;
    errstr = WvString::null;
    // attempt to reset the encoder
    bool success = _reset();
    if (! success)
    {
        if (okay)
            seterror("reset not supported by encoder");
    }
    return success;
}


00075 bool WvEncoder::flushstrbuf(WvStringParm instr, WvBuf &outbuf,
    bool finish)
{
    WvConstStringBuffer inbuf(instr);
    bool success = encode(inbuf, outbuf, true, finish);
    return success;
}


00084 bool WvEncoder::flushstrstr(WvStringParm instr, WvString &outstr,
    bool finish)
{
    WvConstStringBuffer inbuf(instr);
    WvDynBuf outbuf;
    bool success = encode(inbuf, outbuf, true, finish);
    outstr.append(outbuf.getstr());
    return success;
}


00095 bool WvEncoder::encodebufstr(WvBuf &inbuf, WvString &outstr,
    bool flush, bool finish)
{
    WvDynBuf outbuf;
    bool success = encode(inbuf, outbuf, flush, finish);
    outstr.append(outbuf.getstr());
    return success;
}


00105 WvString WvEncoder::strflushstr(WvStringParm instr, bool finish)
{
    WvString outstr;
    flushstrstr(instr, outstr, finish);
    return outstr;
}


00113 WvString WvEncoder::strflushbuf(WvBuf &inbuf, bool finish)
{
    WvString outstr;
    flushbufstr(inbuf, outstr, finish);
    return outstr;
}


00121 bool WvEncoder::flushmembuf(const void *inmem, size_t inlen,
    WvBuf &outbuf, bool finish)
{
    WvConstInPlaceBuf inbuf(inmem, inlen);
    bool success = encode(inbuf, outbuf, true, finish);
    return success;
}


00130 bool WvEncoder::flushmemmem(const void *inmem, size_t inlen,
    void *outmem, size_t *outlen, bool finish)
{
    WvConstInPlaceBuf inbuf(inmem, inlen);
    return encodebufmem(inbuf, outmem, outlen, true, finish);
}


00138 bool WvEncoder::encodebufmem(WvBuf &inbuf,
    void *outmem, size_t *outlen, bool flush, bool finish)
{
    WvInPlaceBuf outbuf(outmem, 0, *outlen);
    bool success = encode(inbuf, outbuf, true, finish);
    *outlen = outbuf.used();
    return success;
}


00148 bool WvEncoder::flushstrmem(WvStringParm instr,
    void *outmem, size_t *outlen, bool finish)
{
    WvConstStringBuffer inbuf(instr);
    return flushbufmem(inbuf, outmem, outlen, finish);
}


00156 WvString WvEncoder::strflushmem(const void *inmem, size_t inlen, bool finish)
{
    WvConstInPlaceBuf inbuf(inmem, inlen);
    return strflushbuf(inbuf, finish);
}


/***** WvNullEncoder *****/

00165 bool WvNullEncoder::_encode(WvBuf &in, WvBuf &out, bool flush)
{
    in.zap();
    return true;
}


00172 bool WvNullEncoder::_reset()
{
    return true;
}



/***** WvPassthroughEncoder *****/

WvPassthroughEncoder::WvPassthroughEncoder()
{
    _reset();
}


00187 bool WvPassthroughEncoder::_encode(WvBuf &in, WvBuf &out, bool flush)
{
    total += in.used();
    out.merge(in);
    return true;
}


00195 bool WvPassthroughEncoder::_reset()
{
    total = 0;
    return true;
}



/***** WvEncoderChain *****/

00205 WvEncoderChain::WvEncoderChain()
{
}


00210 WvEncoderChain::~WvEncoderChain()
{
}


00215 bool WvEncoderChain::_isok() const
{
    WvEncoderChainElemListBase::Iter it(
        const_cast<WvEncoderChainElemListBase&>(encoders));
    for (it.rewind(); it.next(); )
    {
        WvEncoderChainElem *encelem = it.ptr();
        if (! encelem->enc->isok())
            return false;
    }
    return true;
}


00229 bool WvEncoderChain::_isfinished() const
{
    WvEncoderChainElemListBase::Iter it(
        const_cast<WvEncoderChainElemListBase&>(encoders));
    for (it.rewind(); it.next(); )
    {
        WvEncoderChainElem *encelem = it.ptr();
        if (encelem->enc->isfinished())
            return true;
    }
    return false;
}


00243 WvString WvEncoderChain::_geterror() const
{
    WvEncoderChainElemListBase::Iter it(
        const_cast<WvEncoderChainElemListBase&>(encoders));
    for (it.rewind(); it.next(); )
    {
        WvEncoderChainElem *encelem = it.ptr();
        WvString message = encelem->enc->geterror();
        if (!! message)
            return message;
    }
    return WvString::null;
}


// NOTE: In this function we deliberately ignore deep isok() and
//       isfinished() results to allow addition/removal of
//       individual broken encoders while still processing data
//       through as much of the chain as possible.
00262 bool WvEncoderChain::_encode(WvBuf &in, WvBuf &out, bool flush)
{
    if (encoders.isempty())
        return passthrough.encode(in, out, flush);

    // iterate over all encoders in the list
    bool success = true;
    WvEncoderChainElemListBase::Iter it(encoders);
    it.rewind();
    it.next();
    for (WvBuf *tmpin = & in;;)
    {
        // merge pending output and select an output buffer
        WvEncoderChainElem *encelem = it.ptr();
        bool hasnext = it.next();
        WvBuf *tmpout;
        if (! hasnext)
        {
            out.merge(encelem->out);
            tmpout = & out;
        }
        else
            tmpout = & encelem->out;

        // encode
        if (! encelem->enc->encode(*tmpin, *tmpout, flush))
            success = false;

        if (! hasnext)
            break;
        tmpin = & encelem->out;
    }
    return success;
}


// NOTE: In this function we deliberately ignore deep isok() and
//       isfinished() results to allow addition/removal of
//       individual broken encoders while still processing data
//       through as much of the chain as possible.
00302 bool WvEncoderChain::_finish(WvBuf &out)
{
    if (encoders.isempty())
        return true;
    
    // iterate over all encoders in the list
    bool success = true;
    WvEncoderChainElemListBase::Iter it(encoders);
    it.rewind();
    it.next();
    bool needs_flush = false;
    for (WvBuf *tmpin = NULL;;)
    {
        // merge pending output and select an output buffer
        WvEncoderChainElem *encelem = it.ptr();
        bool hasnext = it.next();
        WvBuf *tmpout;
        if (! hasnext)
        {
            out.merge(encelem->out);
            tmpout = & out;
        }
        else
            tmpout = & encelem->out;

        // do we need to flush first due to new input?
        size_t oldused = tmpout->used();
        if (needs_flush)
        {
            if (! encelem->enc->flush(*tmpin, *tmpout))
                success = false;
            needs_flush = true;
        }
        
        // tell the encoder to finish
        if (! encelem->enc->finish(*tmpout))
            success = false;
            
        // check whether any new data was generated
        if (oldused != tmpout->used())
            needs_flush = true;

        if (! hasnext)
            break;
        tmpin = & encelem->out;
    }
    return success;
}


00352 bool WvEncoderChain::_reset()
{
    bool success = true;
    WvEncoderChainElemListBase::Iter it(encoders);
    for (it.rewind(); it.next(); )
    {
        WvEncoderChainElem *encelem = it.ptr();
        encelem->out.zap();
        if (! encelem->enc->reset())
            success = false;
    }
    return success;
}


00367 void WvEncoderChain::append(WvEncoder *enc, bool autofree)
{
    encoders.append(new WvEncoderChainElem(enc, autofree), true);
}


00373 void WvEncoderChain::prepend(WvEncoder *enc, bool autofree)
{
    encoders.prepend(new WvEncoderChainElem(enc, autofree), true);
}

00378 bool WvEncoderChain::get_autofree(WvEncoder *enc)
{
    WvEncoderChainElemListBase::Iter i(encoders);
    for (i.rewind(); i.next(); )
    {
      if ((i.ptr()->enc == enc) && (i.cur()->auto_free))
          return true;
    }
    return false;
}

00389 void WvEncoderChain::set_autofree(WvEncoder *enc, bool autofree)
{
    WvEncoderChainElemListBase::Iter i(encoders);
    if (autofree)
    {
      // Ensure only the first encoder has autofree set
      bool first = true;
      for (i.rewind(); i.next(); )
      {
          if (i.ptr()->enc == enc)
          {
            if (first)
            {
                i.cur()->auto_free = true;
                first = false;
            }
            else
                i.cur()->auto_free = false;
          }
      }
    }
    else
    {
      // Clear autofree for all encoders
      for (i.rewind(); i.next(); )
          if (i.ptr()->enc == enc)
            i.cur()->auto_free = false;
    }
}

00419 void WvEncoderChain::unlink(WvEncoder *enc)
{
    WvEncoderChainElemListBase::Iter it(encoders);
    for (it.rewind(); it.next(); )
    {
        WvEncoderChainElem *encelem = it.ptr();
        if (encelem->enc == enc)
            it.xunlink();
    }
}

00430 void WvEncoderChain::zap()
{
    encoders.zap();
}

Generated by  Doxygen 1.6.0   Back to index