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