diff options
Diffstat (limited to '')
-rw-r--r-- | comm/mailnews/db/mork/morkSink.cpp | 247 |
1 files changed, 247 insertions, 0 deletions
diff --git a/comm/mailnews/db/mork/morkSink.cpp b/comm/mailnews/db/mork/morkSink.cpp new file mode 100644 index 0000000000..daf1bc1b9c --- /dev/null +++ b/comm/mailnews/db/mork/morkSink.cpp @@ -0,0 +1,247 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef _MDB_ +# include "mdb.h" +#endif + +#ifndef _MORK_ +# include "mork.h" +#endif + +#ifndef _MORKSINK_ +# include "morkSink.h" +#endif + +#ifndef _MORKENV_ +# include "morkEnv.h" +#endif + +#ifndef _MORKBLOB_ +# include "morkBlob.h" +#endif + +// 456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789 + +/*virtual*/ morkSink::~morkSink() { + mSink_At = 0; + mSink_End = 0; +} + +/*virtual*/ void morkSpool::FlushSink( + morkEnv* ev) // sync mSpool_Coil->mBuf_Fill +{ + morkCoil* coil = mSpool_Coil; + if (coil) { + mork_u1* body = (mork_u1*)coil->mBuf_Body; + if (body) { + mork_u1* at = mSink_At; + mork_u1* end = mSink_End; + if (at >= body && at <= end) // expected cursor order? + { + mork_fill fill = (mork_fill)(at - body); // current content size + if (fill <= coil->mBlob_Size) + coil->mBuf_Fill = fill; + else { + coil->BlobFillOverSizeError(ev); + coil->mBuf_Fill = coil->mBlob_Size; // make it safe + } + } else + this->BadSpoolCursorOrderError(ev); + } else + coil->NilBufBodyError(ev); + } else + this->NilSpoolCoilError(ev); +} + +/*virtual*/ void morkSpool::SpillPutc(morkEnv* ev, + int c) // grow coil and write byte +{ + morkCoil* coil = mSpool_Coil; + if (coil) { + mork_u1* body = (mork_u1*)coil->mBuf_Body; + if (body) { + mork_u1* at = mSink_At; + mork_u1* end = mSink_End; + if (at >= body && at <= end) // expected cursor order? + { + mork_size size = coil->mBlob_Size; + mork_fill fill = (mork_fill)(at - body); // current content size + if (fill <= size) // less content than medium size? + { + coil->mBuf_Fill = fill; + if (at >= end) // need to grow the coil? + { + if (size > 2048) // grow slower over 2K? + size += 512; + else { + mork_size growth = (size * 4) / 3; // grow by 33% + if (growth < 64) // grow faster under (64 * 3)? + growth = 64; + size += growth; + } + if (coil->GrowCoil(ev, size)) // made coil bigger? + { + body = (mork_u1*)coil->mBuf_Body; + if (body) // have a coil body? + { + mSink_At = at = body + fill; + mSink_End = end = body + coil->mBlob_Size; + } else + coil->NilBufBodyError(ev); + } + } + if (ev->Good()) // seem ready to write byte c? + { + if (at < end) // morkSink::Putc() would succeed? + { + *at++ = (mork_u1)c; + mSink_At = at; + coil->mBuf_Fill = fill + 1; + } else + this->BadSpoolCursorOrderError(ev); + } + } else // fill exceeds size + { + coil->BlobFillOverSizeError(ev); + coil->mBuf_Fill = coil->mBlob_Size; // make it safe + } + } else + this->BadSpoolCursorOrderError(ev); + } else + coil->NilBufBodyError(ev); + } else + this->NilSpoolCoilError(ev); +} + +// ````` ````` ````` ````` ````` ````` ````` ````` +// public: // public non-poly morkSink methods + +/*virtual*/ +morkSpool::~morkSpool() +// Zero all slots to show this sink is disabled, but destroy no memory. +// Note it is typically unnecessary to flush this coil sink, since all +// content is written directly to the coil without any buffering. +{ + mSink_At = 0; + mSink_End = 0; + mSpool_Coil = 0; +} + +morkSpool::morkSpool(morkEnv* ev, morkCoil* ioCoil) + // After installing the coil, calls Seek(ev, 0) to prepare for writing. + : morkSink(), mSpool_Coil(0) { + mSink_At = 0; // set correctly later in Seek() + mSink_End = 0; // set correctly later in Seek() + + if (ev->Good()) { + if (ioCoil) { + mSpool_Coil = ioCoil; + this->Seek(ev, /*pos*/ 0); + } else + ev->NilPointerError(); + } +} + +// ----- All boolean return values below are equal to ev->Good(): ----- + +/*static*/ void morkSpool::BadSpoolCursorOrderError(morkEnv* ev) { + ev->NewError("bad morkSpool cursor order"); +} + +/*static*/ void morkSpool::NilSpoolCoilError(morkEnv* ev) { + ev->NewError("nil mSpool_Coil"); +} + +mork_bool morkSpool::Seek(morkEnv* ev, mork_pos inPos) +// Changed the current write position in coil's buffer to inPos. +// For example, to start writing the coil from scratch, use inPos==0. +{ + morkCoil* coil = mSpool_Coil; + if (coil) { + mork_size minSize = (mork_size)(inPos + 64); + + if (coil->mBlob_Size < minSize) coil->GrowCoil(ev, minSize); + + if (ev->Good()) { + coil->mBuf_Fill = (mork_fill)inPos; + mork_u1* body = (mork_u1*)coil->mBuf_Body; + if (body) { + mSink_At = body + inPos; + mSink_End = body + coil->mBlob_Size; + } else + coil->NilBufBodyError(ev); + } + } else + this->NilSpoolCoilError(ev); + + return ev->Good(); +} + +mork_bool morkSpool::Write(morkEnv* ev, const void* inBuf, mork_size inSize) +// write inSize bytes of inBuf to current position inside coil's buffer +{ + // This method is conceptually very similar to morkStream::Write(), + // and this code was written while looking at that method for clues. + + morkCoil* coil = mSpool_Coil; + if (coil) { + mork_u1* body = (mork_u1*)coil->mBuf_Body; + if (body) { + if (inBuf && inSize) // anything to write? + { + mork_u1* at = mSink_At; + mork_u1* end = mSink_End; + if (at >= body && at <= end) // expected cursor order? + { + // note coil->mBuf_Fill can be stale after morkSink::Putc(): + mork_pos fill = at - body; // current content size + mork_num space = (mork_num)(end - at); // space left in body + if (space < inSize) // not enough to hold write? + { + mork_size minGrowth = space + 16; + mork_size minSize = coil->mBlob_Size + minGrowth; + if (coil->GrowCoil(ev, minSize)) { + body = (mork_u1*)coil->mBuf_Body; + if (body) { + mSink_At = at = body + fill; + mSink_End = end = body + coil->mBlob_Size; + space = (mork_num)(end - at); // space left in body + } else + coil->NilBufBodyError(ev); + } + } + if (ev->Good()) { + if (space >= inSize) // enough room to hold write? + { + MORK_MEMCPY(at, inBuf, inSize); // into body + mSink_At = at + inSize; // advance past written bytes + coil->mBuf_Fill = fill + inSize; // "flush" to fix fill + } else + ev->NewError("insufficient morkSpool space"); + } + } else + this->BadSpoolCursorOrderError(ev); + } + } else + coil->NilBufBodyError(ev); + } else + this->NilSpoolCoilError(ev); + + return ev->Good(); +} + +mork_bool morkSpool::PutString(morkEnv* ev, const char* inString) +// call Write() with inBuf=inString and inSize=strlen(inString), +// unless inString is null, in which case we then do nothing at all. +{ + if (inString) { + mork_size size = strlen(inString); + this->Write(ev, inString, size); + } + return ev->Good(); +} + +// 456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789 |