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 }