diff options
Diffstat (limited to '')
-rw-r--r-- | comm/mailnews/db/mork/morkStream.cpp | 790 |
1 files changed, 790 insertions, 0 deletions
diff --git a/comm/mailnews/db/mork/morkStream.cpp b/comm/mailnews/db/mork/morkStream.cpp new file mode 100644 index 0000000000..23fd7b91ae --- /dev/null +++ b/comm/mailnews/db/mork/morkStream.cpp @@ -0,0 +1,790 @@ +/* -*- 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 _MORKNODE_ +# include "morkNode.h" +#endif + +#ifndef _MORKFILE_ +# include "morkFile.h" +#endif + +#ifndef _MORKENV_ +# include "morkEnv.h" +#endif + +#ifndef _MORKSTREAM_ +# include "morkStream.h" +#endif + +// 456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789 + +// ````` ````` ````` ````` ````` +// { ===== begin morkNode interface ===== + +/*public virtual*/ void morkStream::CloseMorkNode( + morkEnv* ev) // CloseStream() only if open +{ + if (this->IsOpenNode()) { + this->MarkClosing(); + this->CloseStream(ev); + this->MarkShut(); + } +} + +/*public virtual*/ +morkStream::~morkStream() // assert CloseStream() executed earlier +{ + MORK_ASSERT(mStream_ContentFile == 0); + MORK_ASSERT(mStream_Buf == 0); +} + +/*public non-poly*/ +morkStream::morkStream(morkEnv* ev, const morkUsage& inUsage, + nsIMdbHeap* ioHeap, nsIMdbFile* ioContentFile, + mork_size inBufSize, mork_bool inFrozen) + : morkFile(ev, inUsage, ioHeap, ioHeap), + mStream_At(0), + mStream_ReadEnd(0), + mStream_WriteEnd(0) + + , + mStream_ContentFile(0) + + , + mStream_Buf(0), + mStream_BufSize(inBufSize), + mStream_BufPos(0), + mStream_Dirty(morkBool_kFalse), + mStream_HitEof(morkBool_kFalse) { + if (ev->Good()) { + if (inBufSize < morkStream_kMinBufSize) + mStream_BufSize = inBufSize = morkStream_kMinBufSize; + else if (inBufSize > morkStream_kMaxBufSize) + mStream_BufSize = inBufSize = morkStream_kMaxBufSize; + + if (ioContentFile && ioHeap) { + // if ( ioContentFile->FileFrozen() ) // forced to be readonly? + // inFrozen = morkBool_kTrue; // override the input value + + nsIMdbFile_SlotStrongFile(ioContentFile, ev, &mStream_ContentFile); + if (ev->Good()) { + mork_u1* buf = 0; + ioHeap->Alloc(ev->AsMdbEnv(), inBufSize, (void**)&buf); + if (buf) { + mStream_At = mStream_Buf = buf; + + if (!inFrozen) { + // physical buffer end never moves: + mStream_WriteEnd = buf + inBufSize; + } else + mStream_WriteEnd = 0; // no writing is allowed + + if (inFrozen) { + // logical buffer end starts at Buf with no content: + mStream_ReadEnd = buf; + this->SetFileFrozen(inFrozen); + } else + mStream_ReadEnd = 0; // no reading is allowed + + this->SetFileActive(morkBool_kTrue); + this->SetFileIoOpen(morkBool_kTrue); + } + if (ev->Good()) mNode_Derived = morkDerived_kStream; + } + } else + ev->NilPointerError(); + } +} + +/*public non-poly*/ void morkStream::CloseStream( + morkEnv* ev) // called by CloseMorkNode(); +{ + if (this->IsNode()) { + nsIMdbFile_SlotStrongFile((nsIMdbFile*)0, ev, &mStream_ContentFile); + nsIMdbHeap* heap = mFile_SlotHeap; + mork_u1* buf = mStream_Buf; + mStream_Buf = 0; + + if (heap && buf) heap->Free(ev->AsMdbEnv(), buf); + + this->CloseFile(ev); + this->MarkShut(); + } else + this->NonNodeError(ev); +} + +// } ===== end morkNode methods ===== +// ````` ````` ````` ````` ````` + +#define morkStream_kSpacesPerIndent 1 /* one space per indent */ +#define morkStream_kMaxIndentDepth 70 /* max indent of 70 space bytes */ +static const char morkStream_kSpaces[] // next line to ease length perception + = " " + " "; +// 123456789_123456789_123456789_123456789_123456789_123456789_123456789_ +// morkStream_kSpaces above must contain (at least) 70 spaces (ASCII 0x20) + +mork_size morkStream::PutIndent(morkEnv* ev, mork_count inDepth) +// PutIndent() puts a linebreak, and then +// "indents" by inDepth, and returns the line length after indentation. +{ + mork_size outLength = 0; + nsIMdbEnv* mev = ev->AsMdbEnv(); + if (ev->Good()) { + this->PutLineBreak(ev); + if (ev->Good()) { + outLength = inDepth; + mdb_size bytesWritten; + if (inDepth) this->Write(mev, morkStream_kSpaces, inDepth, &bytesWritten); + } + } + return outLength; +} + +mork_size morkStream::PutByteThenIndent(morkEnv* ev, int inByte, + mork_count inDepth) +// PutByteThenIndent() puts the byte, then a linebreak, and then +// "indents" by inDepth, and returns the line length after indentation. +{ + mork_size outLength = 0; + nsIMdbEnv* mev = ev->AsMdbEnv(); + + if (inDepth > morkStream_kMaxIndentDepth) + inDepth = morkStream_kMaxIndentDepth; + + this->Putc(ev, inByte); + if (ev->Good()) { + this->PutLineBreak(ev); + if (ev->Good()) { + outLength = inDepth; + mdb_size bytesWritten; + if (inDepth) this->Write(mev, morkStream_kSpaces, inDepth, &bytesWritten); + } + } + return outLength; +} + +mork_size morkStream::PutStringThenIndent(morkEnv* ev, const char* inString, + mork_count inDepth) +// PutStringThenIndent() puts the string, then a linebreak, and then +// "indents" by inDepth, and returns the line length after indentation. +{ + mork_size outLength = 0; + mdb_size bytesWritten; + nsIMdbEnv* mev = ev->AsMdbEnv(); + + if (inDepth > morkStream_kMaxIndentDepth) + inDepth = morkStream_kMaxIndentDepth; + + if (inString) { + mork_size length = strlen(inString); + if (length && ev->Good()) // any bytes to write? + this->Write(mev, inString, length, &bytesWritten); + } + + if (ev->Good()) { + this->PutLineBreak(ev); + if (ev->Good()) { + outLength = inDepth; + if (inDepth) this->Write(mev, morkStream_kSpaces, inDepth, &bytesWritten); + } + } + return outLength; +} + +mork_size morkStream::PutString(morkEnv* ev, const char* inString) { + nsIMdbEnv* mev = ev->AsMdbEnv(); + mork_size outSize = 0; + mdb_size bytesWritten; + if (inString) { + outSize = strlen(inString); + if (outSize && ev->Good()) // any bytes to write? + { + this->Write(mev, inString, outSize, &bytesWritten); + } + } + return outSize; +} + +mork_size morkStream::PutStringThenNewline(morkEnv* ev, const char* inString) +// PutStringThenNewline() returns total number of bytes written. +{ + nsIMdbEnv* mev = ev->AsMdbEnv(); + mork_size outSize = 0; + mdb_size bytesWritten; + if (inString) { + outSize = strlen(inString); + if (outSize && ev->Good()) // any bytes to write? + { + this->Write(mev, inString, outSize, &bytesWritten); + if (ev->Good()) outSize += this->PutLineBreak(ev); + } + } + return outSize; +} + +mork_size morkStream::PutByteThenNewline(morkEnv* ev, int inByte) +// PutByteThenNewline() returns total number of bytes written. +{ + mork_size outSize = 1; // one for the following byte + this->Putc(ev, inByte); + if (ev->Good()) outSize += this->PutLineBreak(ev); + return outSize; +} + +mork_size morkStream::PutLineBreak(morkEnv* ev) { +#if defined(MORK_MAC) + + this->Putc(ev, mork_kCR); + return 1; + +#else +# if defined(MORK_WIN) + + this->Putc(ev, mork_kCR); + this->Putc(ev, mork_kLF); + return 2; + +# else +# ifdef MORK_UNIX + + this->Putc(ev, mork_kLF); + return 1; + +# endif /* MORK_UNIX */ +# endif /* MORK_WIN */ +#endif /* MORK_MAC */ +} +// ````` ````` ````` ````` ````` ````` ````` ````` +// public: // virtual morkFile methods + +NS_IMETHODIMP +morkStream::Steal(nsIMdbEnv* mev, nsIMdbFile* ioThief) +// Steal: tell this file to close any associated i/o stream in the file +// system, because the file ioThief intends to reopen the file in order +// to provide the MDB implementation with more exotic file access than is +// offered by the nsIMdbFile alone. Presumably the thief knows enough +// from Path() in order to know which file to reopen. If Steal() is +// successful, this file should probably delegate all future calls to +// the nsIMdbFile interface down to the thief files, so that even after +// the file has been stolen, it can still be read, written, or forcibly +// closed (by a call to CloseMdbObject()). +{ + MORK_USED_1(ioThief); + morkEnv* ev = morkEnv::FromMdbEnv(mev); + ev->StubMethodOnlyError(); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +morkStream::BecomeTrunk(nsIMdbEnv* mev) +// If this file is a file version branch created by calling AcquireBud(), +// BecomeTrunk() causes this file's content to replace the original +// file's content, typically by assuming the original file's identity. +{ + morkEnv* ev = morkEnv::FromMdbEnv(mev); + ev->StubMethodOnlyError(); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +morkStream::AcquireBud(nsIMdbEnv* mev, nsIMdbHeap* ioHeap, nsIMdbFile** acqBud) +// AcquireBud() starts a new "branch" version of the file, empty of content, +// so that a new version of the file can be written. This new file +// can later be told to BecomeTrunk() the original file, so the branch +// created by budding the file will replace the original file. Some +// file subclasses might initially take the unsafe but expedient +// approach of simply truncating this file down to zero length, and +// then returning the same morkFile pointer as this, with an extra +// reference count increment. Note that the caller of AcquireBud() is +// expected to eventually call CutStrongRef() on the returned file +// in order to release the strong reference. High quality versions +// of morkFile subclasses will create entirely new files which later +// are renamed to become the old file, so that better transactional +// behavior is exhibited by the file, so crashes protect old files. +// Note that AcquireBud() is an illegal operation on readonly files. +{ + MORK_USED_1(ioHeap); + morkFile* outFile = 0; + nsIMdbFile* file = mStream_ContentFile; + morkEnv* ev = morkEnv::FromMdbEnv(mev); + if (this->IsOpenAndActiveFile() && file) { + // figure out how this interacts with buffering and mStream_WriteEnd: + ev->StubMethodOnlyError(); + } else + this->NewFileDownError(ev); + + *acqBud = outFile; + return NS_ERROR_NOT_IMPLEMENTED; +} + +mork_pos morkStream::Length(morkEnv* ev) const // eof +{ + mork_pos outPos = 0; + + nsIMdbFile* file = mStream_ContentFile; + if (this->IsOpenAndActiveFile() && file) { + mork_pos contentEof = 0; + file->Eof(ev->AsMdbEnv(), &contentEof); + if (ev->Good()) { + if (mStream_WriteEnd) // this stream supports writing? + { + // the local buffer might have buffered content past content eof + if (ev->Good()) // no error happened during Length() above? + { + mork_u1* at = mStream_At; + mork_u1* buf = mStream_Buf; + if (at >= buf) // expected cursor order? + { + mork_pos localContent = mStream_BufPos + (at - buf); + if (localContent > contentEof) // buffered past eof? + contentEof = localContent; // return new logical eof + + outPos = contentEof; + } else + this->NewBadCursorOrderError(ev); + } + } else + outPos = contentEof; // frozen files get length from content file + } + } else + this->NewFileDownError(ev); + + return outPos; +} + +void morkStream::NewBadCursorSlotsError(morkEnv* ev) const { + ev->NewError("bad stream cursor slots"); +} + +void morkStream::NewNullStreamBufferError(morkEnv* ev) const { + ev->NewError("null stream buffer"); +} + +void morkStream::NewCantReadSinkError(morkEnv* ev) const { + ev->NewError("can't read stream sink"); +} + +void morkStream::NewCantWriteSourceError(morkEnv* ev) const { + ev->NewError("can't write stream source"); +} + +void morkStream::NewPosBeyondEofError(morkEnv* ev) const { + ev->NewError("stream pos beyond eof"); +} + +void morkStream::NewBadCursorOrderError(morkEnv* ev) const { + ev->NewError("bad stream cursor order"); +} + +NS_IMETHODIMP +morkStream::Tell(nsIMdbEnv* mdbev, mork_pos* aOutPos) const { + nsresult rv = NS_OK; + morkEnv* ev = morkEnv::FromMdbEnv(mdbev); + + NS_ENSURE_ARG_POINTER(aOutPos); + + nsIMdbFile* file = mStream_ContentFile; + if (this->IsOpenAndActiveFile() && file) { + mork_u1* buf = mStream_Buf; + mork_u1* at = mStream_At; + + mork_u1* readEnd = mStream_ReadEnd; // nonzero only if readonly + mork_u1* writeEnd = mStream_WriteEnd; // nonzero only if writeonly + + if (writeEnd) { + if (buf && at >= buf && at <= writeEnd) { + *aOutPos = mStream_BufPos + (at - buf); + } else + this->NewBadCursorOrderError(ev); + } else if (readEnd) { + if (buf && at >= buf && at <= readEnd) { + *aOutPos = mStream_BufPos + (at - buf); + } else + this->NewBadCursorOrderError(ev); + } + } else + this->NewFileDownError(ev); + + return rv; +} + +NS_IMETHODIMP +morkStream::Read(nsIMdbEnv* mdbev, void* outBuf, mork_size inSize, + mork_size* aOutSize) { + NS_ENSURE_ARG_POINTER(aOutSize); + // First we satisfy the request from buffered bytes, if any. Then + // if additional bytes are needed, we satisfy these by direct reads + // from the content file without any local buffering (but we still need + // to adjust the buffer position to reflect the current i/o point). + + morkEnv* ev = morkEnv::FromMdbEnv(mdbev); + nsresult rv = NS_OK; + + nsIMdbFile* file = mStream_ContentFile; + if (this->IsOpenAndActiveFile() && file) { + mork_u1* end = mStream_ReadEnd; // byte after last buffered byte + if (end) // file is open for read access? + { + if (inSize) // caller wants any output? + { + mork_u1* sink = (mork_u1*)outBuf; // where we plan to write bytes + if (sink) // caller passed good buffer address? + { + mork_u1* at = mStream_At; + mork_u1* buf = mStream_Buf; + if (at >= buf && at <= end) // expected cursor order? + { + mork_num remaining = (mork_num)(end - at); // bytes left in buffer + + mork_num quantum = inSize; // number of bytes to copy + if (quantum > remaining) // more than buffer content? + quantum = remaining; // restrict to buffered bytes + + if (quantum) // any bytes left in the buffer? + { + MORK_MEMCPY(sink, at, quantum); // from buffer bytes + + at += quantum; // advance past read bytes + mStream_At = at; + *aOutSize += quantum; // this much copied so far + + sink += quantum; // in case we need to copy more + inSize -= quantum; // filled this much of request + mStream_HitEof = morkBool_kFalse; + } + + if (inSize) // we still need to read more content? + { + // We need to read more bytes directly from the + // content file, without local buffering. We have + // exhausted the local buffer, so we need to show + // it is now empty, and adjust the current buf pos. + + mork_num posDelta = (mork_num)(at - buf); // old buf content + mStream_BufPos += posDelta; // past now empty buf + + mStream_At = mStream_ReadEnd = buf; // empty buffer + + // file->Seek(ev, mStream_BufPos); // set file pos + // if ( ev->Good() ) // no seek error? + // { + // } + + mork_num actual = 0; + nsIMdbEnv* menv = ev->AsMdbEnv(); + file->Get(menv, sink, inSize, mStream_BufPos, &actual); + if (ev->Good()) // no read error? + { + if (actual) { + *aOutSize += actual; + mStream_BufPos += actual; + mStream_HitEof = morkBool_kFalse; + } else if (!*aOutSize) + mStream_HitEof = morkBool_kTrue; + } + } + } else + this->NewBadCursorOrderError(ev); + } else + this->NewNullStreamBufferError(ev); + } + } else + this->NewCantReadSinkError(ev); + } else + this->NewFileDownError(ev); + + if (ev->Bad()) *aOutSize = 0; + + return rv; +} + +NS_IMETHODIMP +morkStream::Seek(nsIMdbEnv* mdbev, mork_pos inPos, mork_pos* aOutPos) { + NS_ENSURE_ARG_POINTER(aOutPos); + morkEnv* ev = morkEnv::FromMdbEnv(mdbev); + *aOutPos = 0; + nsresult rv = NS_OK; + nsIMdbFile* file = mStream_ContentFile; + if (this->IsOpenOrClosingNode() && this->FileActive() && file) { + mork_u1* at = mStream_At; // current position in buffer + mork_u1* buf = mStream_Buf; // beginning of buffer + mork_u1* readEnd = mStream_ReadEnd; // nonzero only if readonly + mork_u1* writeEnd = mStream_WriteEnd; // nonzero only if writeonly + + if (writeEnd) // file is mutable/writeonly? + { + if (mStream_Dirty) // need to commit buffer changes? + this->Flush(mdbev); + + if (ev->Good()) // no errors during flush or earlier? + { + if (at == buf) // expected post flush cursor value? + { + if (mStream_BufPos != inPos) // need to change pos? + { + mork_pos eof = 0; + nsIMdbEnv* menv = ev->AsMdbEnv(); + file->Eof(menv, &eof); + if (ev->Good()) // no errors getting length? + { + if (inPos <= eof) // acceptable new position? + { + mStream_BufPos = inPos; // new stream position + *aOutPos = inPos; + } else + this->NewPosBeyondEofError(ev); + } + } + } else + this->NewBadCursorOrderError(ev); + } + } else if (readEnd) // file is frozen/readonly? + { + if (at >= buf && at <= readEnd) // expected cursor order? + { + mork_pos eof = 0; + nsIMdbEnv* menv = ev->AsMdbEnv(); + file->Eof(menv, &eof); + if (ev->Good()) // no errors getting length? + { + if (inPos <= eof) // acceptable new position? + { + *aOutPos = inPos; + mStream_BufPos = inPos; // new stream position + mStream_At = mStream_ReadEnd = buf; // empty buffer + if (inPos == eof) // notice eof reached? + mStream_HitEof = morkBool_kTrue; + } else + this->NewPosBeyondEofError(ev); + } + } else + this->NewBadCursorOrderError(ev); + } + + } else + this->NewFileDownError(ev); + + return rv; +} + +NS_IMETHODIMP +morkStream::Write(nsIMdbEnv* menv, const void* inBuf, mork_size inSize, + mork_size* aOutSize) { + mork_num outActual = 0; + morkEnv* ev = morkEnv::FromMdbEnv(menv); + + nsIMdbFile* file = mStream_ContentFile; + if (this->IsOpenActiveAndMutableFile() && file) { + mork_u1* end = mStream_WriteEnd; // byte after last buffered byte + if (end) // file is open for write access? + { + if (inSize) // caller provided any input? + { + const mork_u1* source = (const mork_u1*)inBuf; // from where + if (source) // caller passed good buffer address? + { + mork_u1* at = mStream_At; + mork_u1* buf = mStream_Buf; + if (at >= buf && at <= end) // expected cursor order? + { + mork_num space = (mork_num)(end - at); // space left in buffer + + mork_num quantum = inSize; // number of bytes to write + if (quantum > space) // more than buffer size? + quantum = space; // restrict to avail space + + if (quantum) // any space left in the buffer? + { + mStream_Dirty = morkBool_kTrue; // to ensure later flush + MORK_MEMCPY(at, source, quantum); // into buffer + + mStream_At += quantum; // advance past written bytes + outActual += quantum; // this much written so far + + source += quantum; // in case we need to write more + inSize -= quantum; // filled this much of request + } + + if (inSize) // we still need to write more content? + { + // We need to write more bytes directly to the + // content file, without local buffering. We have + // exhausted the local buffer, so we need to flush + // it and empty it, and adjust the current buf pos. + // After flushing, if the rest of the write fits + // inside the buffer, we will put bytes into the + // buffer rather than write them to content file. + + if (mStream_Dirty) + this->Flush(menv); // will update mStream_BufPos + + at = mStream_At; + if (at < buf || at > end) // bad cursor? + this->NewBadCursorOrderError(ev); + + if (ev->Good()) // no errors? + { + space = (mork_num)(end - at); // space left in buffer + if (space > inSize) // write to buffer? + { + mStream_Dirty = morkBool_kTrue; // ensure flush + MORK_MEMCPY(at, source, inSize); // copy + + mStream_At += inSize; // past written bytes + outActual += inSize; // this much written + } else // directly to content file instead + { + // file->Seek(ev, mStream_BufPos); // set pos + // if ( ev->Good() ) // no seek error? + // { + // } + + mork_num actual = 0; + file->Put(menv, source, inSize, mStream_BufPos, &actual); + if (ev->Good()) // no write error? + { + outActual += actual; + mStream_BufPos += actual; + } + } + } + } + } else + this->NewBadCursorOrderError(ev); + } else + this->NewNullStreamBufferError(ev); + } + } else + this->NewCantWriteSourceError(ev); + } else + this->NewFileDownError(ev); + + if (ev->Bad()) outActual = 0; + + *aOutSize = outActual; + return ev->AsErr(); +} + +NS_IMETHODIMP +morkStream::Flush(nsIMdbEnv* ev) { + morkEnv* mev = morkEnv::FromMdbEnv(ev); + nsresult rv = NS_ERROR_FAILURE; + nsIMdbFile* file = mStream_ContentFile; + if (this->IsOpenOrClosingNode() && this->FileActive() && file) { + if (mStream_Dirty) this->spill_buf(mev); + + rv = file->Flush(ev); + } else + this->NewFileDownError(mev); + return rv; +} + +// ````` ````` ````` ````` ````` ````` ````` ````` +// protected: // protected non-poly morkStream methods (for char io) + +int morkStream::fill_getc(morkEnv* ev) { + int c = EOF; + + nsIMdbFile* file = mStream_ContentFile; + if (this->IsOpenAndActiveFile() && file) { + mork_u1* buf = mStream_Buf; + mork_u1* end = mStream_ReadEnd; // beyond buf after earlier read + if (end > buf) // any earlier read bytes buffered? + { + mStream_BufPos += (end - buf); // advance past old read + } + + if (ev->Good()) // no errors yet? + { + // file->Seek(ev, mStream_BufPos); // set file pos + // if ( ev->Good() ) // no seek error? + // { + // } + + nsIMdbEnv* menv = ev->AsMdbEnv(); + mork_num actual = 0; + file->Get(menv, buf, mStream_BufSize, mStream_BufPos, &actual); + if (ev->Good()) // no read errors? + { + if (actual > mStream_BufSize) // more than asked for?? + actual = mStream_BufSize; + + mStream_At = buf; + mStream_ReadEnd = buf + actual; + if (actual) // any bytes actually read? + { + c = *mStream_At++; // return first byte from buffer + mStream_HitEof = morkBool_kFalse; + } else + mStream_HitEof = morkBool_kTrue; + } + } + } else + this->NewFileDownError(ev); + + return c; +} + +void morkStream::spill_putc(morkEnv* ev, int c) { + this->spill_buf(ev); + if (ev->Good() && mStream_At < mStream_WriteEnd) this->Putc(ev, c); +} + +void morkStream::spill_buf(morkEnv* ev) // spill/flush from buffer to file +{ + nsIMdbFile* file = mStream_ContentFile; + if (this->IsOpenOrClosingNode() && this->FileActive() && file) { + mork_u1* buf = mStream_Buf; + if (mStream_Dirty) { + mork_u1* at = mStream_At; + if (at >= buf && at <= mStream_WriteEnd) // order? + { + mork_num count = (mork_num)(at - buf); // bytes buffered + if (count) // anything to write to the string? + { + if (count > mStream_BufSize) // no more than max? + { + count = mStream_BufSize; + mStream_WriteEnd = buf + mStream_BufSize; + this->NewBadCursorSlotsError(ev); + } + if (ev->Good()) { + // file->Seek(ev, mStream_BufPos); + // if ( ev->Good() ) + // { + // } + nsIMdbEnv* menv = ev->AsMdbEnv(); + mork_num actual = 0; + + file->Put(menv, buf, count, mStream_BufPos, &actual); + if (ev->Good()) { + mStream_BufPos += actual; // past bytes written + mStream_At = buf; // reset buffer cursor + mStream_Dirty = morkBool_kFalse; + } + } + } + } else + this->NewBadCursorOrderError(ev); + } else { +#ifdef MORK_DEBUG + ev->NewWarning("stream:spill:not:dirty"); +#endif /*MORK_DEBUG*/ + } + } else + this->NewFileDownError(ev); +} + +// 456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789 |