diff options
Diffstat (limited to 'db/mork/src/morkStream.cpp')
-rw-r--r-- | db/mork/src/morkStream.cpp | 859 |
1 files changed, 859 insertions, 0 deletions
diff --git a/db/mork/src/morkStream.cpp b/db/mork/src/morkStream.cpp new file mode 100644 index 000000000..26c6f443e --- /dev/null +++ b/db/mork/src/morkStream.cpp @@ -0,0 +1,859 @@ +/* -*- 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 + +//3456789_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 = MORK_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 = MORK_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 = MORK_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("cant read stream sink"); } + +void morkStream::NewCantWriteSourceError(morkEnv* ev) const +{ ev->NewError("cant 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); + +} + + +//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789 |