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 Tue Oct 5 01:09:20 2004 for WvStreams by doxygen 1.3.7