00001
00002
00003
00004
00005
00006
00007 #include "wvencoder.h"
00008
00009
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
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
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
00061 okay = true;
00062 finished = false;
00063 errstr = WvString::null;
00064
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
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
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
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
00259
00260
00261
00262 bool WvEncoderChain::_encode(WvBuf &in, WvBuf &out, bool flush)
00263 {
00264 if (encoders.isempty())
00265 return passthrough.encode(in, out, flush);
00266
00267
00268 bool success = true;
00269 WvEncoderChainElemListBase::Iter it(encoders);
00270 it.rewind();
00271 it.next();
00272 for (WvBuf *tmpin = & in;;)
00273 {
00274
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
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
00299
00300
00301
00302 bool WvEncoderChain::_finish(WvBuf &out)
00303 {
00304 if (encoders.isempty())
00305 return true;
00306
00307
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
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
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
00337 if (! encelem->enc->finish(*tmpout))
00338 success = false;
00339
00340
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 }