From 2e5950d728028dabfaaed8ae191c3b0532c5f4b8 Mon Sep 17 00:00:00 2001 From: "bienvenu%netscape.com" Date: Mon, 15 Mar 1999 01:32:31 +0000 Subject: [PATCH] latest mork drop, fix commit code --- db/mork/src/morkConfig.h | 8 +- db/mork/src/morkFile.cpp | 15 +- db/mork/src/morkFile.h | 3 +- db/mork/src/morkParser.cpp | 12 + db/mork/src/morkParser.h | 212 ++++++++--------- db/mork/src/morkRowSpace.cpp | 4 +- db/mork/src/morkStream.cpp | 173 ++++++++++++-- db/mork/src/morkStream.h | 36 ++- db/mork/src/morkWriter.cpp | 316 +++++++++++++++++++------- db/mork/src/morkWriter.h | 54 ++++- mailnews/db/mork/src/morkConfig.h | 8 +- mailnews/db/mork/src/morkFile.cpp | 15 +- mailnews/db/mork/src/morkFile.h | 3 +- mailnews/db/mork/src/morkParser.cpp | 12 + mailnews/db/mork/src/morkParser.h | 212 ++++++++--------- mailnews/db/mork/src/morkRowSpace.cpp | 4 +- mailnews/db/mork/src/morkStream.cpp | 173 ++++++++++++-- mailnews/db/mork/src/morkStream.h | 36 ++- mailnews/db/mork/src/morkWriter.cpp | 316 +++++++++++++++++++------- mailnews/db/mork/src/morkWriter.h | 54 ++++- 20 files changed, 1200 insertions(+), 466 deletions(-) diff --git a/db/mork/src/morkConfig.h b/db/mork/src/morkConfig.h index d46203f182b5..5670a4ae9ffb 100644 --- a/db/mork/src/morkConfig.h +++ b/db/mork/src/morkConfig.h @@ -48,13 +48,16 @@ #endif // } %%%%% end platform defs peculiar to Mork %%%%% -#if defined (MORK_WIN) || defined(MORK_UNIX) +#if defined (MORK_WIN) || defined(MORK_UNIX) #include "stdio.h" +#include "ctype.h" #include "errno.h" #include "string.h" #include "memory.h" #include "nsDebug.h" +#define MORK_ISPRINT(c) isprint(c) + #define MORK_FILETELL(file) ftell(file) #define MORK_FILESEEK(file, where, how) fseek(file, where, how) #define MORK_FILEREAD(outbuf, insize, file) fread(outbuf, insize, 1, file) @@ -64,6 +67,9 @@ #ifdef MORK_MAC #include "xp_file.h" +#include "ctype.h" + +#define MORK_ISPRINT(c) isprint(c) #define MORK_FILETELL(file) XP_FileTell(file) #define MORK_FILESEEK(file, where, how) XP_FileSeek(file, where, how) diff --git a/db/mork/src/morkFile.cpp b/db/mork/src/morkFile.cpp index 3fc80c79e982..5436caa3612d 100644 --- a/db/mork/src/morkFile.cpp +++ b/db/mork/src/morkFile.cpp @@ -239,18 +239,23 @@ morkFile::NewFileErrnoError(morkEnv* ev) const # endif /* MORK_WIN */ #endif /* MORK_MAC */ -void +mork_size morkFile::WriteNewlines(morkEnv* ev, mork_count inNewlines) + // WriteNewlines() returns the number of bytes written. { + mork_size outSize = 0; while ( inNewlines && ev->Good() ) // more newlines to write? { mork_u4 quantum = inNewlines; if ( quantum > morkFile_kNewlinesCount ) quantum = morkFile_kNewlinesCount; - this->Write(ev, morkFile_kNewlines, quantum * mork_kNewlineSize); + mork_size quantumSize = quantum * mork_kNewlineSize; + this->Write(ev, morkFile_kNewlines, quantumSize); + outSize += quantumSize; inNewlines -= quantum; } + return outSize; } // ````` ````` ````` ````` ````` @@ -309,7 +314,7 @@ morkStdioFile::OpenOldStdioFile(morkEnv* ev, nsIMdbHeap* ioHeap, morkStdioFile* outFile = 0; if ( ioHeap && inFilePath ) { - const char* mode = (inFrozen)? "r" : "w"; + const char* mode = (inFrozen)? "rb" : "wb"; outFile = new(*ioHeap, ev) morkStdioFile(ev, morkUsage::kHeap, ioHeap, ioHeap, inFilePath, mode); @@ -331,7 +336,7 @@ morkStdioFile::CreateNewStdioFile(morkEnv* ev, nsIMdbHeap* ioHeap, morkStdioFile* outFile = 0; if ( ioHeap && inFilePath ) { - const char* mode = "w+"; + const char* mode = "wb+"; outFile = new(*ioHeap, ev) morkStdioFile(ev, morkUsage::kHeap, ioHeap, ioHeap, inFilePath, mode); } @@ -386,7 +391,7 @@ morkStdioFile::AcquireBud(morkEnv* ev, nsIMdbHeap* ioHeap) this->SetFileIoOpen(morkBool_kFalse); mStdioFile_File = 0; - file = fopen(name, "w+"); // open for write, discarding old content + file = fopen(name, "wb+"); // open for write, discarding old content if ( file ) { mStdioFile_File = file; diff --git a/db/mork/src/morkFile.h b/db/mork/src/morkFile.h index c8ef65809a45..29358e07e97f 100644 --- a/db/mork/src/morkFile.h +++ b/db/mork/src/morkFile.h @@ -159,7 +159,8 @@ public: // non-poly morkFile methods void NewFileErrnoError(morkEnv* ev) const; // call NewFileErrnoError() to convert std C errno into AB fault - void WriteNewlines(morkEnv* ev, mork_count inNewlines); + mork_size WriteNewlines(morkEnv* ev, mork_count inNewlines); + // WriteNewlines() returns the number of bytes written. public: // typesafe refcounting inlines calling inherited morkNode methods static void SlotWeakFile(morkFile* me, diff --git a/db/mork/src/morkParser.cpp b/db/mork/src/morkParser.cpp index 4aefa6905d1f..bfec6374e7ee 100644 --- a/db/mork/src/morkParser.cpp +++ b/db/mork/src/morkParser.cpp @@ -44,6 +44,14 @@ #include "morkStream.h" #endif +#ifndef _MORKBLOB_ +#include "morkBlob.h" +#endif + +#ifndef _MORKSINK_ +#include "morkSink.h" +#endif + //3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789 // ````` ````` ````` ````` ````` @@ -131,6 +139,10 @@ morkParser::CloseParser(morkEnv* ev) /*i*/ // called by CloseMorkNode(); { if ( !this->IsShutNode() ) { + mParser_ScopeSpool.CloseSpool(ev); + mParser_ValueSpool.CloseSpool(ev); + mParser_ColumnSpool.CloseSpool(ev); + mParser_StringSpool.CloseSpool(ev); nsIMdbHeap_SlotStrongHeap((nsIMdbHeap*) 0, ev, &mParser_Heap); morkStream::SlotStrongStream((morkStream*) 0, ev, &mParser_Stream); this->MarkShut(); diff --git a/db/mork/src/morkParser.h b/db/mork/src/morkParser.h index 8c724bc92124..50a7d27e67d9 100644 --- a/db/mork/src/morkParser.h +++ b/db/mork/src/morkParser.h @@ -209,73 +209,73 @@ class morkParser /*d*/ : public morkNode { protected: // protected morkParser members nsIMdbHeap* mParser_Heap; // refcounted heap used for allocation - morkStream* mParser_Stream; // refcounted input stream - - mork_u4 mParser_Tag; // must equal morkParser_kTag - mork_count mParser_MoreGranularity; // constructor inBytesPerParseSegment + morkStream* mParser_Stream; // refcounted input stream - mork_u4 mParser_State; // state where parser should resume - - // after finding ends of group transactions, we can re-seek the start: - mork_pos mParser_GroupContentStartPos; // start of this group - - mork_gid mParser_GroupId; // group ID if inside a group - mork_tid mParser_TableId; // table ID if inside a table - mork_rid mParser_RowId; // row ID if inside a row - - mork_bool mParser_InPort; // called OnNewPort but not OnPortEnd? - mork_bool mParser_InDict; // called OnNewDict but not OnDictEnd? - mork_bool mParser_InCell; // called OnNewCell but not OnCellEnd? - mork_bool mParser_InMeta; // called OnNewMeta but not OnMetaEnd? - - mork_bool mParser_InPortRow; // called OnNewPortRow but not OnPortRowEnd? - mork_bool mParser_IsBroken; // has the parse become broken? - mork_bool mParser_IsDone; // has the parse finished? - mork_bool mParser_DoMore; // mParser_MoreGranularity not exhausted? - - mork_change mParser_Change; // driven by modifier in text - - morkAlias mParser_Alias; // current alias being parsed - // note that mParser_Alias.mAlias_Buf points at mParser_ScopeSpool below: - - // blob spools allocated in mParser_Heap - morkSpool mParser_ScopeSpool; // place to accumulate ID scope blobs - morkSpool mParser_ValueSpool; // place to accumulate value blobs - morkSpool mParser_ColumnSpool; // place to accumulate column blobs - morkSpool mParser_StringSpool; // place to accumulate string blobs - - morkSpoolSink mParser_ScopeSink; // writes to mParser_ScopeSpool - morkSpoolSink mParser_ValueSink; // writes to mParser_ValueSpool - morkSpoolSink mParser_ColumnSink; // writes to mParser_ColumnSpool - morkSpoolSink mParser_StringSink; // writes to mParser_StringSpool + mork_u4 mParser_Tag; // must equal morkParser_kTag + mork_count mParser_MoreGranularity; // constructor inBytesPerParseSegment + + mork_u4 mParser_State; // state where parser should resume + + // after finding ends of group transactions, we can re-seek the start: + mork_pos mParser_GroupContentStartPos; // start of this group + + mork_gid mParser_GroupId; // group ID if inside a group + mork_tid mParser_TableId; // table ID if inside a table + mork_rid mParser_RowId; // row ID if inside a row + + mork_bool mParser_InPort; // called OnNewPort but not OnPortEnd? + mork_bool mParser_InDict; // called OnNewDict but not OnDictEnd? + mork_bool mParser_InCell; // called OnNewCell but not OnCellEnd? + mork_bool mParser_InMeta; // called OnNewMeta but not OnMetaEnd? + + mork_bool mParser_InPortRow; // called OnNewPortRow but not OnPortRowEnd? + mork_bool mParser_IsBroken; // has the parse become broken? + mork_bool mParser_IsDone; // has the parse finished? + mork_bool mParser_DoMore; // mParser_MoreGranularity not exhausted? + + mork_change mParser_Change; // driven by modifier in text + + morkAlias mParser_Alias; // current alias being parsed + // note that mParser_Alias.mAlias_Buf points at mParser_ScopeSpool below: + + // blob spools allocated in mParser_Heap + morkSpool mParser_ScopeSpool; // place to accumulate ID scope blobs + morkSpool mParser_ValueSpool; // place to accumulate value blobs + morkSpool mParser_ColumnSpool; // place to accumulate column blobs + morkSpool mParser_StringSpool; // place to accumulate string blobs + + morkSpoolSink mParser_ScopeSink; // writes to mParser_ScopeSpool + morkSpoolSink mParser_ValueSink; // writes to mParser_ValueSpool + morkSpoolSink mParser_ColumnSink; // writes to mParser_ColumnSpool + morkSpoolSink mParser_StringSink; // writes to mParser_StringSpool + + // yarns allocated in mParser_Heap + morkYarn mParser_AliasYarn; // place to receive from AliasToYarn() - // yarns allocated in mParser_Heap - morkYarn mParser_AliasYarn; // place to receive from AliasToYarn() - // span showing current ongoing file position status: - morkSpan mParser_PortSpan; // span of current db port file - - // various spans denoting nested subspaces inside the file's port span: - morkSpan mParser_GroupSpan; // span of current transaction group - morkSpan mParser_DictSpan; - morkSpan mParser_AliasSpan; - morkSpan mParser_MetaSpan; - morkSpan mParser_TableSpan; - morkSpan mParser_RowSpan; - morkSpan mParser_CellSpan; - morkSpan mParser_ColumnSpan; - morkSpan mParser_SlotSpan; + morkSpan mParser_PortSpan; // span of current db port file + + // various spans denoting nested subspaces inside the file's port span: + morkSpan mParser_GroupSpan; // span of current transaction group + morkSpan mParser_DictSpan; + morkSpan mParser_AliasSpan; + morkSpan mParser_MetaSpan; + morkSpan mParser_TableSpan; + morkSpan mParser_RowSpan; + morkSpan mParser_CellSpan; + morkSpan mParser_ColumnSpan; + morkSpan mParser_SlotSpan; private: // convenience inlines - mork_pos HerePos() const - { return mParser_PortSpan.mSpan_End.mPlace_Pos; } + mork_pos HerePos() const + { return mParser_PortSpan.mSpan_End.mPlace_Pos; } - void SetHerePos(mork_pos inPos) - { mParser_PortSpan.mSpan_End.mPlace_Pos = inPos; } - - void AddLine() - { ++ mParser_PortSpan.mSpan_End.mPlace_Line; } + void SetHerePos(mork_pos inPos) + { mParser_PortSpan.mSpan_End.mPlace_Pos = inPos; } + + void AddLine() + { ++ mParser_PortSpan.mSpan_End.mPlace_Line; } // { ===== begin morkNode interface ===== public: // morkNode virtual methods @@ -353,64 +353,64 @@ public: // out virtual morkParser methods, data flow parser to subclass // mp:Slot ::= OnValue | OnValueAlias | OnRowAlias | OnTableAlias - // Note that in interfaces below, mork_change parameters kAdd and kNil - // both mean about the same thing by default. Only kCut is interesting, - // because this usually means to remove members instead of adding them. + // Note that in interfaces below, mork_change parameters kAdd and kNil + // both mean about the same thing by default. Only kCut is interesting, + // because this usually means to remove members instead of adding them. - virtual void OnNewPort(morkEnv* ev, const morkPlace& inPlace) = 0; - virtual void OnPortGlitch(morkEnv* ev, const morkGlitch& inGlitch) = 0; - virtual void OnPortEnd(morkEnv* ev, const morkSpan& inSpan) = 0; + virtual void OnNewPort(morkEnv* ev, const morkPlace& inPlace) = 0; + virtual void OnPortGlitch(morkEnv* ev, const morkGlitch& inGlitch) = 0; + virtual void OnPortEnd(morkEnv* ev, const morkSpan& inSpan) = 0; - virtual void OnNewGroup(morkEnv* ev, const morkPlace& inPlace, mork_gid inGid) = 0; - virtual void OnGroupGlitch(morkEnv* ev, const morkGlitch& inGlitch) = 0; - virtual void OnGroupCommitEnd(morkEnv* ev, const morkSpan& inSpan) = 0; - virtual void OnGroupAbortEnd(morkEnv* ev, const morkSpan& inSpan) = 0; + virtual void OnNewGroup(morkEnv* ev, const morkPlace& inPlace, mork_gid inGid) = 0; + virtual void OnGroupGlitch(morkEnv* ev, const morkGlitch& inGlitch) = 0; + virtual void OnGroupCommitEnd(morkEnv* ev, const morkSpan& inSpan) = 0; + virtual void OnGroupAbortEnd(morkEnv* ev, const morkSpan& inSpan) = 0; - virtual void OnNewPortRow(morkEnv* ev, const morkPlace& inPlace, - const morkAlias& inAlias, mork_change inChange) = 0; - virtual void OnPortRowGlitch(morkEnv* ev, const morkGlitch& inGlitch) = 0; - virtual void OnPortRowEnd(morkEnv* ev, const morkSpan& inSpan) = 0; + virtual void OnNewPortRow(morkEnv* ev, const morkPlace& inPlace, + const morkAlias& inAlias, mork_change inChange) = 0; + virtual void OnPortRowGlitch(morkEnv* ev, const morkGlitch& inGlitch) = 0; + virtual void OnPortRowEnd(morkEnv* ev, const morkSpan& inSpan) = 0; - virtual void OnNewTable(morkEnv* ev, const morkPlace& inPlace, - const morkAlias& inAlias, mork_change inChange) = 0; - virtual void OnTableGlitch(morkEnv* ev, const morkGlitch& inGlitch) = 0; - virtual void OnTableEnd(morkEnv* ev, const morkSpan& inSpan) = 0; - - virtual void OnNewMeta(morkEnv* ev, const morkPlace& inPlace) = 0; - virtual void OnMetaGlitch(morkEnv* ev, const morkGlitch& inGlitch) = 0; - virtual void OnMetaEnd(morkEnv* ev, const morkSpan& inSpan) = 0; + virtual void OnNewTable(morkEnv* ev, const morkPlace& inPlace, + const morkAlias& inAlias, mork_change inChange) = 0; + virtual void OnTableGlitch(morkEnv* ev, const morkGlitch& inGlitch) = 0; + virtual void OnTableEnd(morkEnv* ev, const morkSpan& inSpan) = 0; + + virtual void OnNewMeta(morkEnv* ev, const morkPlace& inPlace) = 0; + virtual void OnMetaGlitch(morkEnv* ev, const morkGlitch& inGlitch) = 0; + virtual void OnMetaEnd(morkEnv* ev, const morkSpan& inSpan) = 0; - virtual void OnNewRow(morkEnv* ev, const morkPlace& inPlace, - const morkAlias& inAlias, mork_change inChange) = 0; - virtual void OnRowGlitch(morkEnv* ev, const morkGlitch& inGlitch) = 0; - virtual void OnRowEnd(morkEnv* ev, const morkSpan& inSpan) = 0; + virtual void OnNewRow(morkEnv* ev, const morkPlace& inPlace, + const morkAlias& inAlias, mork_change inChange) = 0; + virtual void OnRowGlitch(morkEnv* ev, const morkGlitch& inGlitch) = 0; + virtual void OnRowEnd(morkEnv* ev, const morkSpan& inSpan) = 0; - virtual void OnNewDict(morkEnv* ev, const morkPlace& inPlace) = 0; - virtual void OnDictGlitch(morkEnv* ev, const morkGlitch& inGlitch) = 0; - virtual void OnDictEnd(morkEnv* ev, const morkSpan& inSpan) = 0; + virtual void OnNewDict(morkEnv* ev, const morkPlace& inPlace) = 0; + virtual void OnDictGlitch(morkEnv* ev, const morkGlitch& inGlitch) = 0; + virtual void OnDictEnd(morkEnv* ev, const morkSpan& inSpan) = 0; - virtual void OnAlias(morkEnv* ev, const morkSpan& inSpan, - const morkAlias& inAlias) = 0; + virtual void OnAlias(morkEnv* ev, const morkSpan& inSpan, + const morkAlias& inAlias) = 0; - virtual void OnAliasGlitch(morkEnv* ev, const morkGlitch& inGlitch) = 0; + virtual void OnAliasGlitch(morkEnv* ev, const morkGlitch& inGlitch) = 0; - virtual void OnNewCell(morkEnv* ev, const morkPlace& inPlace, - const morkAlias& inAlias, mork_change inChange) = 0; - virtual void OnCellGlitch(morkEnv* ev, const morkGlitch& inGlitch) = 0; - virtual void OnCellForm(morkEnv* ev, mork_cscode inCharsetFormat) = 0; - virtual void OnCellEnd(morkEnv* ev, const morkSpan& inSpan) = 0; - - virtual void OnValue(morkEnv* ev, const morkSpan& inSpan, - const morkBuf& inBuf) = 0; + virtual void OnNewCell(morkEnv* ev, const morkPlace& inPlace, + const morkAlias& inAlias, mork_change inChange) = 0; + virtual void OnCellGlitch(morkEnv* ev, const morkGlitch& inGlitch) = 0; + virtual void OnCellForm(morkEnv* ev, mork_cscode inCharsetFormat) = 0; + virtual void OnCellEnd(morkEnv* ev, const morkSpan& inSpan) = 0; + + virtual void OnValue(morkEnv* ev, const morkSpan& inSpan, + const morkBuf& inBuf) = 0; - virtual void OnValueAlias(morkEnv* ev, const morkSpan& inSpan, - const morkAlias& inAlias) = 0; + virtual void OnValueAlias(morkEnv* ev, const morkSpan& inSpan, + const morkAlias& inAlias) = 0; - virtual void OnRowAlias(morkEnv* ev, const morkSpan& inSpan, - const morkAlias& inAlias) = 0; + virtual void OnRowAlias(morkEnv* ev, const morkSpan& inSpan, + const morkAlias& inAlias) = 0; - virtual void OnTableAlias(morkEnv* ev, const morkSpan& inSpan, - const morkAlias& inAlias) = 0; + virtual void OnTableAlias(morkEnv* ev, const morkSpan& inSpan, + const morkAlias& inAlias) = 0; // ````` ````` ````` ````` ````` ````` ````` ````` protected: // protected parser helper methods diff --git a/db/mork/src/morkRowSpace.cpp b/db/mork/src/morkRowSpace.cpp index c3f18ed45e5a..ff7b3bcc32f1 100644 --- a/db/mork/src/morkRowSpace.cpp +++ b/db/mork/src/morkRowSpace.cpp @@ -327,7 +327,7 @@ morkRowSpace::NewRowWithOid(morkEnv* ev, const mdbOid* inOid) { row->InitRow(ev, inOid, this, /*length*/ 0, pool); - if ( ev->Good() ) + if ( ev->Good() && mRowSpace_Rows.AddRow(ev, row) ) outRow = row; else pool->ZapRow(ev, row); @@ -354,7 +354,7 @@ morkRowSpace::NewRow(morkEnv* ev) { row->InitRow(ev, &oid, this, /*length*/ 0, pool); - if ( ev->Good() ) + if ( ev->Good() && mRowSpace_Rows.AddRow(ev, row) ) outRow = row; else pool->ZapRow(ev, row); diff --git a/db/mork/src/morkStream.cpp b/db/mork/src/morkStream.cpp index edfe864280e8..e7d33fe4239e 100644 --- a/db/mork/src/morkStream.cpp +++ b/db/mork/src/morkStream.cpp @@ -156,74 +156,201 @@ morkStream::CloseStream(morkEnv* ev) // called by CloseMorkNode(); // } ===== 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; -void + if ( ev->Good() ) + { + this->PutLineBreak(ev); + if ( ev->Good() ) + { + outLength = inDepth; + if ( inDepth ) + this->Write(ev, morkStream_kSpaces, inDepth); + } + } + 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; + + if ( inDepth > morkStream_kMaxIndentDepth ) + inDepth = morkStream_kMaxIndentDepth; + + this->Putc(ev, inByte); + if ( ev->Good() ) + { + this->PutLineBreak(ev); + if ( ev->Good() ) + { + outLength = inDepth; + if ( inDepth ) + this->Write(ev, morkStream_kSpaces, inDepth); + } + } + 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; + + 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(ev, inString, length); + } + + if ( ev->Good() ) + { + this->PutLineBreak(ev); + if ( ev->Good() ) + { + outLength = inDepth; + if ( inDepth ) + this->Write(ev, morkStream_kSpaces, inDepth); + } + } + return outLength; +} + +mork_size morkStream::PutString(morkEnv* ev, const char* inString) { + mork_size outSize = 0; if ( inString ) { - mork_num length = MORK_STRLEN(inString); - if ( length && ev->Good() ) // any bytes to write? + outSize = MORK_STRLEN(inString); + if ( outSize && ev->Good() ) // any bytes to write? { - this->Write(ev, inString, length); + this->Write(ev, inString, outSize); } } + return outSize; } -void +mork_size morkStream::PutStringThenNewline(morkEnv* ev, const char* inString) + // PutStringThenNewline() returns total number of bytes written. { + mork_size outSize = 0; if ( inString ) { - mork_num length = MORK_STRLEN(inString); - if ( length && ev->Good() ) // any bytes to write? + outSize = MORK_STRLEN(inString); + if ( outSize && ev->Good() ) // any bytes to write? { - this->Write(ev, inString, length); + this->Write(ev, inString, outSize); if ( ev->Good() ) - this->WriteNewlines(ev, /*count*/ 1); + outSize += this->PutLineBreak(ev); } } + return outSize; } -void +mork_size morkStream::PutStringThenNewlineThenSpace(morkEnv* ev, const char* inString) + // PutStringThenNewlineThenSpace() returns total number of bytes written. { + mork_size outSize = 0; if ( inString ) { - mork_num length = MORK_STRLEN(inString); - if ( length && ev->Good() ) // any bytes to write? + outSize = MORK_STRLEN(inString); + if ( outSize && ev->Good() ) // any bytes to write? { - this->Write(ev, inString, length); + this->Write(ev, inString, outSize); if ( ev->Good() ) { - this->WriteNewlines(ev, /*count*/ 1); + outSize += this->PutLineBreak(ev); if ( ev->Good() ) + { this->Putc(ev, ' '); + ++outSize; + } } } } + return outSize; } -void +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() ) - this->WriteNewlines(ev, /*count*/ 1); + outSize += this->PutLineBreak(ev); + return outSize; } -void +mork_size morkStream::PutByteThenNewlineThenSpace(morkEnv* ev, int inByte) + // PutByteThenNewlineThenSpace() returns total number of bytes written. { + mork_size outSize = 1; // one for the following byte this->Putc(ev, inByte); if ( ev->Good() ) { - this->WriteNewlines(ev, /*count*/ 1); + outSize += this->PutLineBreak(ev); if ( ev->Good() ) + { this->Putc(ev, ' '); + ++outSize; + } } + return outSize; } +mork_size +morkStream::PutLineBreak(morkEnv* ev) +{ +#ifdef MORK_MAC + + this->Putc(ev, mork_kCR); + return 1; + +#else +# if defined(MORK_WIN) || defined(MORK_OS2) + + 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 @@ -719,13 +846,9 @@ morkStream::spill_buf(morkEnv* ev) // spill/flush from buffer to file } else { -#ifdef AB_CONFIG_TRACE - this->TraceObject(ev); -#endif /*AB_CONFIG_TRACE*/ - -#ifdef AB_CONFIG_DEBUG - ev->Break("", (long) this); -#endif /*AB_CONFIG_DEBUG*/ +#ifdef MORK_DEBUG + ev->NewWarning("stream:spill:not:dirty"); +#endif /*MORK_DEBUG*/ } } else this->NewFileDownError(ev); diff --git a/db/mork/src/morkStream.h b/db/mork/src/morkStream.h index b536c9eb677b..464383fcef3f 100644 --- a/db/mork/src/morkStream.h +++ b/db/mork/src/morkStream.h @@ -63,7 +63,7 @@ **| else branch of the statement calls a function that raises an appropriate **| error to complain about either reading a sink or writing a source. **| -**|| morkStream is a direct clone of mork_Stream from Communicator 4.5's +**|| morkStream is a direct clone of ab_Stream from Communicator 4.5's **| address book code, which in turn was based on the stream class in the **| public domain Mithril programming language. |*/ @@ -164,11 +164,33 @@ public: // public non-poly morkStream methods morkFile* GetStreamContentFile() const { return mStream_ContentFile; } mork_size GetStreamBufferSize() const { return mStream_BufSize; } - void PutString(morkEnv* ev, const char* inString); - void PutStringThenNewline(morkEnv* ev, const char* inString); - void PutStringThenNewlineThenSpace(morkEnv* ev, const char* inString); - void PutByteThenNewline(morkEnv* ev, int inByte); - void PutByteThenNewlineThenSpace(morkEnv* ev, int inByte); + mork_size PutIndent(morkEnv* ev, mork_count inDepth); + // PutIndent() puts a linebreak, and then + // "indents" by inDepth, and returns the line length after indentation. + + mork_size 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 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 PutString(morkEnv* ev, const char* inString); + // PutString() returns the length of the string written. + + mork_size PutStringThenNewline(morkEnv* ev, const char* inString); + // PutStringThenNewline() returns total number of bytes written. + + mork_size PutStringThenNewlineThenSpace(morkEnv* ev, const char* inString); + // PutStringThenNewlineThenSpace() returns total number of bytes written. + + mork_size PutByteThenNewline(morkEnv* ev, int inByte); + // PutByteThenNewline() returns total number of bytes written. + + mork_size PutByteThenNewlineThenSpace(morkEnv* ev, int inByte); + // PutByteThenNewlineThenSpace() returns total number of bytes written. // ````` ````` stdio type methods ````` ````` void Printf(morkEnv* ev, const char* inFormat, ...); @@ -201,6 +223,8 @@ public: // public non-poly morkStream methods else spill_putc(ev, c); } + + mork_size PutLineBreak(morkEnv* ev); public: // typesafe refcounting inlines calling inherited morkNode methods static void SlotWeakStream(morkStream* me, diff --git a/db/mork/src/morkWriter.cpp b/db/mork/src/morkWriter.cpp index 23a353693bfe..2fc18064c0a0 100644 --- a/db/mork/src/morkWriter.cpp +++ b/db/mork/src/morkWriter.cpp @@ -120,6 +120,9 @@ morkWriter::morkWriter(morkEnv* ev, const morkUsage& inUsage, , mWriter_TotalCount( morkWriter_kCountNumberOfPhases ) , mWriter_DoneCount( 0 ) + +, mWriter_LineSize( 0 ) +, mWriter_MaxIndent( morkWriter_kMaxIndent ) , mWriter_TableCharset( 0 ) , mWriter_TableAtomScope( 0 ) @@ -150,8 +153,11 @@ morkWriter::morkWriter(morkEnv* ev, const morkUsage& inUsage, , mWriter_RowSpaceTablesIter( ) , mWriter_RowSpaceRowsIter( ) { + mWriter_SafeNameBuf[ 0 ] = 0; + mWriter_SafeNameBuf[ morkWriter_kMaxColumnNameSize * 2 ] = 0; mWriter_ColNameBuf[ 0 ] = 0; mWriter_ColNameBuf[ morkWriter_kMaxColumnNameSize ] = 0; + mdbYarn* y = &mWriter_ColYarn; y->mYarn_Buf = mWriter_ColNameBuf; // where to put col bytes y->mYarn_Fill = 0; // set later by writer @@ -160,6 +166,14 @@ morkWriter::morkWriter(morkEnv* ev, const morkUsage& inUsage, y->mYarn_Form = 0; // set later by writer y->mYarn_Grow = 0; // do not allow buffer growth + y = &mWriter_SafeYarn; + y->mYarn_Buf = mWriter_SafeNameBuf; // where to put col bytes + y->mYarn_Fill = 0; // set later by writer + y->mYarn_Size = morkWriter_kMaxColumnNameSize * 2; // our buf size + y->mYarn_More = 0; // set later by writer + y->mYarn_Form = 0; // set later by writer + y->mYarn_Grow = 0; // do not allow buffer growth + if ( ev->Good() ) { if ( ioSlotHeap && ioFile && ioStore ) @@ -328,20 +342,66 @@ morkWriter::WriteMore(morkEnv* ev) // call until IsWritingDone() is true return ev->Good(); } -void -morkWriter::WriteAtom(morkEnv* ev, const morkAtom* inAtom) -{ - morkBuf buf; // to ref content inside atom +static const char* morkWriter_kHexDigits = "0123456789ABCDEF"; - if ( inAtom->AsBuf(buf) ) +mork_size +morkWriter::WriteYarn(morkEnv* ev, const mdbYarn* inYarn) + // return number of atom bytes written on the current line (which + // implies that escaped line breaks will make the size value smaller + // than the entire yarn's size, since only part goes on a last line). +{ + mork_size outSize = 0; + morkStream* stream = mWriter_Stream; + + const mork_u1* b = (const mork_u1*) inYarn->mYarn_Buf; + if ( b ) { - // actually we need to escape problem characters instead of this: - morkStream* stream = mWriter_Stream; - if ( buf.mBuf_Fill ) // any content to write? - stream->Write(ev, buf.mBuf_Body, buf.mBuf_Fill); + register int c; + mork_fill fill = inYarn->mYarn_Fill; + const mork_u1* end = b + fill; + while ( b < end ) + { + c = *b++; // next byte to print + if ( c < 0x080 && MORK_ISPRINT(c) ) + { + if ( c == ')' && c == '$' && c == '\\' ) + { + stream->Putc(ev, '\\'); + ++outSize; + } + stream->Putc(ev, c); + ++outSize; + } + else + { + outSize += 3; // '$' hex hex + stream->Putc(ev, '$'); + stream->Putc(ev, morkWriter_kHexDigits[ (c >> 4) & 0x0F ]); + stream->Putc(ev, morkWriter_kHexDigits[ c & 0x0F ]); + } + } } + mWriter_LineSize += outSize; + + return outSize; +} + +mork_size +morkWriter::WriteAtom(morkEnv* ev, const morkAtom* inAtom) + // return number of atom bytes written on the current line (which + // implies that escaped line breaks will make the size value smaller + // than the entire atom's size, since only part goes on a last line). +{ + mork_size outSize = 0; + mdbYarn yarn; // to ref content inside atom + + if ( inAtom->AliasYarn(&yarn) ) + outSize = this->WriteYarn(ev, &yarn); + // mWriter_LineSize += stream->Write(ev, inYarn->mYarn_Buf, outSize); else inAtom->BadAtomKindError(ev); + + return outSize; } void @@ -351,10 +411,13 @@ morkWriter::WriteAtomSpaceAsDict(morkEnv* ev, morkAtomSpace* ioSpace) mork_scope scope = ioSpace->mSpace_Scope; if ( scope < 0x80 ) { - stream->WriteNewlines(ev, /*count*/ 1); - stream->PutString(ev, "<<(atomScope="); + if ( mWriter_LineSize ) + stream->PutLineBreak(ev); + stream->PutString(ev, "< <(atomScope="); stream->Putc(ev, (int) scope); - stream->PutStringThenNewline(ev, ")> // (charset=iso-8859-1)"); + ++mWriter_LineSize; + stream->PutString(ev, ")> // (charset=iso-8859-1)"); + mWriter_LineSize = stream->PutIndent(ev, morkWriter_kDictAliasDepth); } else ioSpace->NonAsciiSpaceScopeName(ev); @@ -379,11 +442,18 @@ morkWriter::WriteAtomSpaceAsDict(morkEnv* ev, morkAtomSpace* ioSpace) { atom->mAtom_Change = morkChange_kNil; // neutralize change + this->IndentAsNeeded(ev, morkWriter_kDictAliasDepth); mork_size size = ev->TokenAsHex(idBuf, atom->mBookAtom_Id); - idBuf[ size ] = '='; - stream->Write(ev, buf, size+2); // plus two for '(' and '=' + mWriter_LineSize += stream->Write(ev, buf, size+1); // '(' + + this->IndentAsNeeded(ev, morkWriter_kDictAliasValueDepth); + stream->Putc(ev, '='); // end alias + ++mWriter_LineSize; + this->WriteAtom(ev, atom); - stream->PutByteThenNewlineThenSpace(ev, ')'); // end alias + stream->Putc(ev, ')'); // end alias + ++mWriter_LineSize; + ++mWriter_DoneCount; } else // temporarily warn about wrong change slot value @@ -396,7 +466,10 @@ morkWriter::WriteAtomSpaceAsDict(morkEnv* ev, morkAtomSpace* ioSpace) } if ( ev->Good() ) + { + this->IndentAsNeeded(ev, 0); stream->PutByteThenNewline(ev, '>'); // end dict + } } mork_bool @@ -556,6 +629,7 @@ morkWriter::OnDirtyAllDone(morkEnv* ev) if ( ev->Good() ) { stream->PutStringThenNewline(ev, "// "); + mWriter_LineSize = 0; } if ( ev->Good() ) @@ -570,8 +644,10 @@ mork_bool morkWriter::OnPutHeaderDone(morkEnv* ev) { morkStream* stream = mWriter_Stream; - stream->WriteNewlines(ev, /*count*/ 1); + if ( mWriter_LineSize ) + stream->PutLineBreak(ev); stream->PutStringThenNewline(ev, "// OnPutHeaderDone()"); + mWriter_LineSize = 0; morkStore* store = mWriter_Store; if ( store ) @@ -591,8 +667,10 @@ mork_bool morkWriter::OnRenumberAllDone(morkEnv* ev) { morkStream* stream = mWriter_Stream; - stream->WriteNewlines(ev, /*count*/ 1); + if ( mWriter_LineSize ) + stream->PutLineBreak(ev); stream->PutStringThenNewline(ev, "// OnRenumberAllDone()"); + mWriter_LineSize = 0; if ( ev->Good() ) mWriter_Phase = morkWriter_kPhaseStoreAtomSpaces; @@ -606,8 +684,10 @@ mork_bool morkWriter::OnStoreAtomSpaces(morkEnv* ev) { morkStream* stream = mWriter_Stream; - stream->WriteNewlines(ev, /*count*/ 1); + if ( mWriter_LineSize ) + stream->PutLineBreak(ev); stream->PutStringThenNewline(ev, "// OnStoreAtomSpaces()"); + mWriter_LineSize = 0; if ( ev->Good() ) { @@ -618,6 +698,7 @@ morkWriter::OnStoreAtomSpaces(morkEnv* ev) if ( space ) { stream->PutStringThenNewline(ev, "// ground column space dict:"); + mWriter_LineSize = 0; this->WriteAtomSpaceAsDict(ev, space); } } @@ -637,8 +718,10 @@ mork_bool morkWriter::OnAtomSpaceAtomAids(morkEnv* ev) { morkStream* stream = mWriter_Stream; - stream->WriteNewlines(ev, /*count*/ 1); + if ( mWriter_LineSize ) + stream->PutLineBreak(ev); stream->PutStringThenNewline(ev, "// OnAtomSpaceAtomAids()"); + mWriter_LineSize = 0; if ( ev->Good() ) mWriter_Phase = morkWriter_kPhaseStoreRowSpacesTables; @@ -711,8 +794,10 @@ mork_bool morkWriter::OnStoreRowSpacesTables(morkEnv* ev) { morkStream* stream = mWriter_Stream; - stream->WriteNewlines(ev, /*count*/ 1); + if ( mWriter_LineSize ) + stream->PutLineBreak(ev); stream->PutStringThenNewline(ev, "// OnStoreRowSpacesTables()"); + mWriter_LineSize = 0; // later we'll break this up, but today we'll write all in one shot: this->WriteAllStoreTables(ev); @@ -729,8 +814,10 @@ mork_bool morkWriter::OnRowSpaceTables(morkEnv* ev) { morkStream* stream = mWriter_Stream; - stream->WriteNewlines(ev, /*count*/ 1); + if ( mWriter_LineSize ) + stream->PutLineBreak(ev); stream->PutStringThenNewline(ev, "// OnRowSpaceTables()"); + mWriter_LineSize = 0; if ( ev->Good() ) mWriter_Phase = morkWriter_kPhaseStoreRowSpacesRows; @@ -744,8 +831,10 @@ mork_bool morkWriter::OnTableRowArray(morkEnv* ev) { morkStream* stream = mWriter_Stream; - stream->WriteNewlines(ev, /*count*/ 1); + if ( mWriter_LineSize ) + stream->PutLineBreak(ev); stream->PutStringThenNewline(ev, "// OnTableRowArray()"); + mWriter_LineSize = 0; if ( ev->Good() ) mWriter_Phase = morkWriter_kPhaseStoreRowSpacesRows; @@ -759,8 +848,10 @@ mork_bool morkWriter::OnStoreRowSpacesRows(morkEnv* ev) { morkStream* stream = mWriter_Stream; - stream->WriteNewlines(ev, /*count*/ 1); + if ( mWriter_LineSize ) + stream->PutLineBreak(ev); stream->PutStringThenNewline(ev, "// OnStoreRowSpacesRows()"); + mWriter_LineSize = 0; if ( ev->Good() ) mWriter_Phase = morkWriter_kPhaseContentDone; @@ -774,8 +865,10 @@ mork_bool morkWriter::OnRowSpaceRows(morkEnv* ev) { morkStream* stream = mWriter_Stream; - stream->WriteNewlines(ev, /*count*/ 1); + if ( mWriter_LineSize ) + stream->PutLineBreak(ev); stream->PutStringThenNewline(ev, "// OnRowSpaceRows()"); + mWriter_LineSize = 0; if ( ev->Good() ) mWriter_Phase = morkWriter_kPhaseContentDone; @@ -789,8 +882,10 @@ mork_bool morkWriter::OnContentDone(morkEnv* ev) { morkStream* stream = mWriter_Stream; - stream->WriteNewlines(ev, /*count*/ 1); + if ( mWriter_LineSize ) + stream->PutLineBreak(ev); stream->PutStringThenNewline(ev, "// OnContentDone()"); + mWriter_LineSize = 0; stream->Flush(ev); morkFile* bud = mWriter_Bud; if ( bud ) @@ -820,7 +915,7 @@ mork_bool morkWriter::PutTable(morkEnv* ev, morkTable* ioTable) { if ( ev->Good() ) - this->StartTable(ev, ioTable->mTable_Id); + this->StartTable(ev, ioTable); if ( ev->Good() ) { @@ -904,13 +999,21 @@ morkWriter::WriteTokenToTokenMetaCell(morkEnv* ev, *p++ = '^'; // indicates col is hex ID mork_size colSize = ev->TokenAsHex(p, inCol); - p += colSize; // advance past the col in hex - *p++ = ' '; // space between hex IDs - *p++ = '^'; // indicates value is hex ID - mork_size valSize = ev->TokenAsHex(p, inValue); - p += valSize; // advance past the value in hex - *p = ')'; - stream->Write(ev, buf, colSize + valSize + 5); + p += colSize; + *p++ = '='; // we always start with open paren + mWriter_LineSize += stream->Write(ev, buf, colSize + 3); + + this->IndentAsNeeded(ev, morkWriter_kTableMetaCellValueDepth); + mdbYarn* yarn = &mWriter_ColYarn; + // mork_u1* yarnBuf = (mork_u1*) yarn->mYarn_Buf; + mWriter_Store->TokenToString(ev, inValue, yarn); + this->WriteYarn(ev, yarn); + stream->Putc(ev, ')'); + ++mWriter_LineSize; + + // mork_fill fill = yarn->mYarn_Fill; + // yarnBuf[ fill ] = ')'; // append terminator + // mWriter_LineSize += stream->Write(ev, yarnBuf, fill + 1); // +1 for ')' } void @@ -918,14 +1021,20 @@ morkWriter::WriteStringToTokenDictCell(morkEnv* ev, const char* inCol, mork_token inValue) // Note inCol should begin with '(' and end with '=', with col in between. { - mdbYarn* yarn = &mWriter_ColYarn; - mork_u1* yarnBuf = (mork_u1*) yarn->mYarn_Buf; morkStream* stream = mWriter_Stream; - stream->PutString(ev, inCol); + mWriter_LineSize += stream->PutString(ev, inCol); + + this->IndentAsNeeded(ev, morkWriter_kDictMetaCellValueDepth); + mdbYarn* yarn = &mWriter_ColYarn; + // mork_u1* yarnBuf = (mork_u1*) yarn->mYarn_Buf; mWriter_Store->TokenToString(ev, inValue, yarn); - mork_fill fill = yarn->mYarn_Fill; - yarnBuf[ fill ] = ')'; // append terminator - stream->Write(ev, yarnBuf, fill + 1); // plus one for ')' + this->WriteYarn(ev, yarn); + stream->Putc(ev, ')'); + ++mWriter_LineSize; + + // mork_fill fill = yarn->mYarn_Fill; + // yarnBuf[ fill ] = ')'; // append terminator + // mWriter_LineSize += stream->Write(ev, yarnBuf, fill + 1); // +1 for ')' } void @@ -934,28 +1043,35 @@ morkWriter::StartDict(morkEnv* ev) morkStream* stream = mWriter_Stream; if ( mWriter_DidStartDict ) { - stream->WriteNewlines(ev, /*count*/ 1); + if ( mWriter_LineSize ) + stream->PutLineBreak(ev); stream->PutStringThenNewline(ev, "> // end dict"); + mWriter_LineSize = 0; } mWriter_DidStartDict = morkBool_kTrue; - stream->WriteNewlines(ev, /*count*/ 1); + if ( mWriter_LineSize ) + stream->PutLineBreak(ev); + mWriter_LineSize = 0; if ( mWriter_DictCharset || mWriter_DictAtomScope != 'a' ) { stream->Putc(ev, '<'); + stream->Putc(ev, ' '); stream->Putc(ev, '<'); + mWriter_LineSize = 3; if ( mWriter_DictCharset ) this->WriteStringToTokenDictCell(ev, "(charset=", mWriter_DictCharset); if ( mWriter_DictAtomScope != 'a' ) this->WriteStringToTokenDictCell(ev, "(atomScope=", mWriter_DictAtomScope); - stream->PutByteThenNewlineThenSpace(ev, '>'); + stream->Putc(ev, '>'); + ++mWriter_LineSize; } else { - stream->PutStringThenNewlineThenSpace(ev, - "< // <(charset=iso-8859-1)(atomScope=a)>"); + stream->PutString(ev, "< // <(charset=iso-8859-1)(atomScope=a)>"); } + mWriter_LineSize = stream->PutIndent(ev, morkWriter_kDictAliasDepth); } void @@ -964,45 +1080,63 @@ morkWriter::EndDict(morkEnv* ev) morkStream* stream = mWriter_Stream; if ( mWriter_DidStartDict ) { - stream->WriteNewlines(ev, /*count*/ 1); + if ( mWriter_LineSize ) + stream->PutLineBreak(ev); stream->PutStringThenNewline(ev, "> // end dict"); + mWriter_LineSize = 0; } mWriter_DidStartDict = morkBool_kFalse; } void -morkWriter::StartTable(morkEnv* ev, mork_tid inTid) +morkWriter::StartTable(morkEnv* ev, morkTable* ioTable) { - morkStream* stream = mWriter_Stream; - stream->WriteNewlines(ev, /*count*/ 1); - - char buf[ 64 ]; // buffer for staging hex - char* p = buf; - *p++ = '{'; - mork_size size = ev->TokenAsHex(p, inTid); - p += size; - *p++ = ' '; - *p = '{'; - stream->Write(ev, buf, size + 3); + mdbOid toid; // to receive table oid + ioTable->GetTableOid(ev, &toid); - morkStore* store = mWriter_Store; - mork_scope rs = mWriter_TableRowScope; - if ( rs ) - this->WriteTokenToTokenMetaCell(ev, store->mStore_RowScopeToken, rs); - - mork_kind tk = mWriter_TableKind; - if ( tk ) - this->WriteTokenToTokenMetaCell(ev, store->mStore_TableKindToken, tk); + if ( ev->Good() ) + { + morkStream* stream = mWriter_Stream; + if ( mWriter_LineSize ) + stream->PutLineBreak(ev); + mWriter_LineSize = 0; - stream->PutByteThenNewlineThenSpace(ev, '}'); + char buf[ 64 ]; // buffer for staging hex + char* p = buf; + *p++ = '{'; + mork_size size = ev->OidAsHex(p, toid); + p += size; + *p++ = ' '; + *p = '{'; + mWriter_LineSize += stream->Write(ev, buf, size + 3); + + morkStore* store = mWriter_Store; + mork_scope rs = mWriter_TableRowScope; + if ( rs ) + { + this->IndentAsNeeded(ev, morkWriter_kTableMetaCellDepth); + this->WriteTokenToTokenMetaCell(ev, store->mStore_RowScopeToken, rs); + } + mork_kind tk = mWriter_TableKind; + if ( tk ) + { + this->IndentAsNeeded(ev, morkWriter_kTableMetaCellDepth); + this->WriteTokenToTokenMetaCell(ev, store->mStore_TableKindToken, tk); + } + stream->Putc(ev, '}'); + stream->Putc(ev, ' '); + mWriter_LineSize += 2; + } } void morkWriter::EndTable(morkEnv* ev) { morkStream* stream = mWriter_Stream; - stream->WriteNewlines(ev, /*count*/ 1); + if ( mWriter_LineSize ) + stream->PutLineBreak(ev); stream->PutStringThenNewline(ev, "} // end table"); + mWriter_LineSize = 0; } mork_bool @@ -1018,7 +1152,7 @@ morkWriter::PutRowDict(morkEnv* ev, morkRow* ioRow) morkCell* end = cells + ioRow->mRow_Length; --cells; // prepare for preincrement: - while ( ++cells < end ) + while ( ++cells < end && ev->Good() ) { morkAtom* atom = cells->GetAtom(); if ( atom && atom->mAtom_Change == morkChange_kAdd ) @@ -1027,12 +1161,19 @@ morkWriter::PutRowDict(morkEnv* ev, morkRow* ioRow) { atom->mAtom_Change = morkChange_kNil; // neutralize change + this->IndentAsNeeded(ev, morkWriter_kDictAliasDepth); morkBookAtom* ba = (morkBookAtom*) atom; mork_size size = ev->TokenAsHex(idBuf, ba->mBookAtom_Id); - idBuf[ size ] = '='; - stream->Write(ev, buf, size+2); // plus two for '(' and '=' + mWriter_LineSize += stream->Write(ev, buf, size+1); // '(' + + this->IndentAsNeeded(ev, morkWriter_kDictAliasValueDepth); + stream->Putc(ev, '='); // start value + ++mWriter_LineSize; + this->WriteAtom(ev, atom); - stream->PutByteThenNewlineThenSpace(ev, ')'); // end alias + stream->Putc(ev, ')'); // end alias + ++mWriter_LineSize; + ++mWriter_DoneCount; } } @@ -1067,17 +1208,16 @@ morkWriter::PutRowCells(morkEnv* ev, morkRow* ioRow) colSize = ev->TokenAsHex(p, col); p += colSize; + this->IndentAsNeeded(ev, morkWriter_kRowCellDepth); if ( atom->IsBook() ) // is it possible to write atom ID? { - *p++ = ' '; *p++ = '^'; morkBookAtom* ba = (morkBookAtom*) atom; mork_size valSize = ev->TokenAsHex(p, ba->mBookAtom_Id); p += valSize; *p = ')'; - stream->Write(ev, buf, colSize + valSize + 5); - stream->WriteNewlines(ev, /*count*/ 1); - stream->Putc(ev, ' '); + + mWriter_LineSize += stream->Write(ev, buf, colSize + valSize + 4); if ( atom->mAtom_Change == morkChange_kAdd ) { @@ -1087,10 +1227,15 @@ morkWriter::PutRowCells(morkEnv* ev, morkRow* ioRow) } else // must write an anonymous atom { - *p++ = '='; - stream->Write(ev, buf, colSize + 3); + mWriter_LineSize += stream->Write(ev, buf, colSize + 2); + + this->IndentAsNeeded(ev, morkWriter_kRowCellValueDepth); + stream->Putc(ev, '='); + ++mWriter_LineSize; + this->WriteAtom(ev, atom); - stream->PutByteThenNewlineThenSpace(ev, ')'); // end alias + stream->Putc(ev, ')'); // end alias + ++mWriter_LineSize; } } } @@ -1107,7 +1252,10 @@ morkWriter::PutRow(morkEnv* ev, morkRow* ioRow) mdbOid* roid = &ioRow->mRow_Oid; mork_size ridSize = 0; - if ( ioRow->IsRowDirty() ) + this->IndentAsNeeded(ev, morkWriter_kRowDepth); + + // if ( ioRow->IsRowDirty() ) + if ( morkBool_kTrue ) { ioRow->SetRowClean(); mork_rid rid = roid->mOid_Id; @@ -1119,10 +1267,12 @@ morkWriter::PutRow(morkEnv* ev, morkRow* ioRow) p += ridSize; *p++ = ' '; - stream->Write(ev, buf, ridSize + 2); + mWriter_LineSize += stream->Write(ev, buf, ridSize + 2); this->PutRowCells(ev, ioRow); - stream->PutByteThenNewlineThenSpace(ev, ']'); // end row + stream->Putc(ev, ']'); // end row + stream->Putc(ev, ' '); // end row + mWriter_LineSize += 2; } else { @@ -1131,9 +1281,9 @@ morkWriter::PutRow(morkEnv* ev, morkRow* ioRow) else ridSize = ev->OidAsHex(p, *roid); - stream->Write(ev, buf, ridSize); - stream->WriteNewlines(ev, /*count*/ 1); + mWriter_LineSize += stream->Write(ev, buf, ridSize); stream->Putc(ev, ' '); + ++mWriter_LineSize; } ++mWriter_DoneCount; diff --git a/db/mork/src/morkWriter.h b/db/mork/src/morkWriter.h index c2cb8d4ce6fc..51c79bfd74b5 100644 --- a/db/mork/src/morkWriter.h +++ b/db/mork/src/morkWriter.h @@ -51,6 +51,10 @@ #include "morkRowSpace.h" #endif +#ifndef _MORKSTREAM_ +#include "morkStream.h" +#endif + //3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789 @@ -79,7 +83,22 @@ #define morkWriter_kCountNumberOfPhases 13 /* part of mWrite_TotalCount */ -#define morkWriter_kMaxColumnNameSize 256 /* longest writable col name */ +#define morkWriter_kMaxColumnNameSize 128 /* longest writable col name */ + +#define morkWriter_kMaxIndent 48 /* default value for mWriter_MaxIndent */ + +#define morkWriter_kTableMetaCellDepth 4 /* */ +#define morkWriter_kTableMetaCellValueDepth 6 /* */ + +#define morkWriter_kDictMetaCellDepth 4 /* */ +#define morkWriter_kDictMetaCellValueDepth 6 /* */ + +#define morkWriter_kDictAliasDepth 2 /* */ +#define morkWriter_kDictAliasValueDepth 4 /* */ + +#define morkWriter_kRowDepth 2 /* */ +#define morkWriter_kRowCellDepth 4 /* */ +#define morkWriter_kRowCellValueDepth 6 /* */ class morkWriter : public morkNode { // row iterator @@ -105,6 +124,9 @@ public: // state is public because the entire Mork system is private mork_count mWriter_TotalCount; // count of all things to be written mork_count mWriter_DoneCount; // count of things already written + mork_size mWriter_LineSize; // length of current line being written + mork_size mWriter_MaxIndent; // line size forcing a line break + mork_cscode mWriter_TableCharset; // current charset metainfo mork_scope mWriter_TableAtomScope; // current atom scope mork_scope mWriter_TableRowScope; // current row scope @@ -125,12 +147,18 @@ public: // state is public because the entire Mork system is private mork_bool mWriter_DidEndDict; // true when a dict has been ended mork_pos mWriter_TableRowArrayPos; // index into mTable_RowArray - + + char mWriter_SafeNameBuf[ (morkWriter_kMaxColumnNameSize * 2) + 4 ]; + // Note: extra four bytes in ColNameBuf means we can always append to yarn + char mWriter_ColNameBuf[ morkWriter_kMaxColumnNameSize + 4 ]; // Note: extra four bytes in ColNameBuf means we can always append to yarn mdbYarn mWriter_ColYarn; // a yarn to describe space in ColNameBuf: // mYarn_Buf == mWriter_ColNameBuf, mYarn_Size == morkWriter_kMaxColumnNameSize + + mdbYarn mWriter_SafeYarn; // a yarn to describe space in ColNameBuf: + // mYarn_Buf == mWriter_SafeNameBuf, mYarn_Size == (kMaxColumnNameSize * 2) morkAtomSpaceMapIter mWriter_StoreAtomSpacesIter; // for mStore_AtomSpaces morkAtomAidMapIter mWriter_AtomSpaceAtomAidsIter; // for AtomSpace_AtomAids @@ -169,6 +197,15 @@ public: // typing & errors public: // inlines mork_bool DidStartDict() const { return mWriter_DidStartDict; } mork_bool DidEndDict() const { return mWriter_DidEndDict; } + + mork_bool NeedLineBreak() const + { return ( mWriter_LineSize > mWriter_MaxIndent ); } + + void IndentAsNeeded(morkEnv* ev, mork_size inDepth) + { + if ( mWriter_LineSize > mWriter_MaxIndent ) + mWriter_LineSize = mWriter_Stream->PutIndent(ev, inDepth); + } public: // iterative/asynchronouse writing @@ -220,8 +257,17 @@ public: // writing node content second pass public: // other writer methods + mork_size WriteYarn(morkEnv* ev, const mdbYarn* inYarn); + // return number of atom bytes written on the current line (which + // implies that escaped line breaks will make the size value smaller + // than the entire yarn's size, since only part goes on a last line). + + mork_size WriteAtom(morkEnv* ev, const morkAtom* inAtom); + // return number of atom bytes written on the current line (which + // implies that escaped line breaks will make the size value smaller + // than the entire atom's size, since only part goes on a last line). + void WriteAllStoreTables(morkEnv* ev); - void WriteAtom(morkEnv* ev, const morkAtom* inAtom); void WriteAtomSpaceAsDict(morkEnv* ev, morkAtomSpace* ioSpace); void WriteTokenToTokenMetaCell(morkEnv* ev, mork_token inCol, @@ -233,7 +279,7 @@ public: // other writer methods void StartDict(morkEnv* ev); void EndDict(morkEnv* ev); - void StartTable(morkEnv* ev, mork_tid inTid); + void StartTable(morkEnv* ev, morkTable* ioTable); void EndTable(morkEnv* ev); public: // typesafe refcounting inlines calling inherited morkNode methods diff --git a/mailnews/db/mork/src/morkConfig.h b/mailnews/db/mork/src/morkConfig.h index d46203f182b5..5670a4ae9ffb 100644 --- a/mailnews/db/mork/src/morkConfig.h +++ b/mailnews/db/mork/src/morkConfig.h @@ -48,13 +48,16 @@ #endif // } %%%%% end platform defs peculiar to Mork %%%%% -#if defined (MORK_WIN) || defined(MORK_UNIX) +#if defined (MORK_WIN) || defined(MORK_UNIX) #include "stdio.h" +#include "ctype.h" #include "errno.h" #include "string.h" #include "memory.h" #include "nsDebug.h" +#define MORK_ISPRINT(c) isprint(c) + #define MORK_FILETELL(file) ftell(file) #define MORK_FILESEEK(file, where, how) fseek(file, where, how) #define MORK_FILEREAD(outbuf, insize, file) fread(outbuf, insize, 1, file) @@ -64,6 +67,9 @@ #ifdef MORK_MAC #include "xp_file.h" +#include "ctype.h" + +#define MORK_ISPRINT(c) isprint(c) #define MORK_FILETELL(file) XP_FileTell(file) #define MORK_FILESEEK(file, where, how) XP_FileSeek(file, where, how) diff --git a/mailnews/db/mork/src/morkFile.cpp b/mailnews/db/mork/src/morkFile.cpp index 3fc80c79e982..5436caa3612d 100644 --- a/mailnews/db/mork/src/morkFile.cpp +++ b/mailnews/db/mork/src/morkFile.cpp @@ -239,18 +239,23 @@ morkFile::NewFileErrnoError(morkEnv* ev) const # endif /* MORK_WIN */ #endif /* MORK_MAC */ -void +mork_size morkFile::WriteNewlines(morkEnv* ev, mork_count inNewlines) + // WriteNewlines() returns the number of bytes written. { + mork_size outSize = 0; while ( inNewlines && ev->Good() ) // more newlines to write? { mork_u4 quantum = inNewlines; if ( quantum > morkFile_kNewlinesCount ) quantum = morkFile_kNewlinesCount; - this->Write(ev, morkFile_kNewlines, quantum * mork_kNewlineSize); + mork_size quantumSize = quantum * mork_kNewlineSize; + this->Write(ev, morkFile_kNewlines, quantumSize); + outSize += quantumSize; inNewlines -= quantum; } + return outSize; } // ````` ````` ````` ````` ````` @@ -309,7 +314,7 @@ morkStdioFile::OpenOldStdioFile(morkEnv* ev, nsIMdbHeap* ioHeap, morkStdioFile* outFile = 0; if ( ioHeap && inFilePath ) { - const char* mode = (inFrozen)? "r" : "w"; + const char* mode = (inFrozen)? "rb" : "wb"; outFile = new(*ioHeap, ev) morkStdioFile(ev, morkUsage::kHeap, ioHeap, ioHeap, inFilePath, mode); @@ -331,7 +336,7 @@ morkStdioFile::CreateNewStdioFile(morkEnv* ev, nsIMdbHeap* ioHeap, morkStdioFile* outFile = 0; if ( ioHeap && inFilePath ) { - const char* mode = "w+"; + const char* mode = "wb+"; outFile = new(*ioHeap, ev) morkStdioFile(ev, morkUsage::kHeap, ioHeap, ioHeap, inFilePath, mode); } @@ -386,7 +391,7 @@ morkStdioFile::AcquireBud(morkEnv* ev, nsIMdbHeap* ioHeap) this->SetFileIoOpen(morkBool_kFalse); mStdioFile_File = 0; - file = fopen(name, "w+"); // open for write, discarding old content + file = fopen(name, "wb+"); // open for write, discarding old content if ( file ) { mStdioFile_File = file; diff --git a/mailnews/db/mork/src/morkFile.h b/mailnews/db/mork/src/morkFile.h index c8ef65809a45..29358e07e97f 100644 --- a/mailnews/db/mork/src/morkFile.h +++ b/mailnews/db/mork/src/morkFile.h @@ -159,7 +159,8 @@ public: // non-poly morkFile methods void NewFileErrnoError(morkEnv* ev) const; // call NewFileErrnoError() to convert std C errno into AB fault - void WriteNewlines(morkEnv* ev, mork_count inNewlines); + mork_size WriteNewlines(morkEnv* ev, mork_count inNewlines); + // WriteNewlines() returns the number of bytes written. public: // typesafe refcounting inlines calling inherited morkNode methods static void SlotWeakFile(morkFile* me, diff --git a/mailnews/db/mork/src/morkParser.cpp b/mailnews/db/mork/src/morkParser.cpp index 4aefa6905d1f..bfec6374e7ee 100644 --- a/mailnews/db/mork/src/morkParser.cpp +++ b/mailnews/db/mork/src/morkParser.cpp @@ -44,6 +44,14 @@ #include "morkStream.h" #endif +#ifndef _MORKBLOB_ +#include "morkBlob.h" +#endif + +#ifndef _MORKSINK_ +#include "morkSink.h" +#endif + //3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789 // ````` ````` ````` ````` ````` @@ -131,6 +139,10 @@ morkParser::CloseParser(morkEnv* ev) /*i*/ // called by CloseMorkNode(); { if ( !this->IsShutNode() ) { + mParser_ScopeSpool.CloseSpool(ev); + mParser_ValueSpool.CloseSpool(ev); + mParser_ColumnSpool.CloseSpool(ev); + mParser_StringSpool.CloseSpool(ev); nsIMdbHeap_SlotStrongHeap((nsIMdbHeap*) 0, ev, &mParser_Heap); morkStream::SlotStrongStream((morkStream*) 0, ev, &mParser_Stream); this->MarkShut(); diff --git a/mailnews/db/mork/src/morkParser.h b/mailnews/db/mork/src/morkParser.h index 8c724bc92124..50a7d27e67d9 100644 --- a/mailnews/db/mork/src/morkParser.h +++ b/mailnews/db/mork/src/morkParser.h @@ -209,73 +209,73 @@ class morkParser /*d*/ : public morkNode { protected: // protected morkParser members nsIMdbHeap* mParser_Heap; // refcounted heap used for allocation - morkStream* mParser_Stream; // refcounted input stream - - mork_u4 mParser_Tag; // must equal morkParser_kTag - mork_count mParser_MoreGranularity; // constructor inBytesPerParseSegment + morkStream* mParser_Stream; // refcounted input stream - mork_u4 mParser_State; // state where parser should resume - - // after finding ends of group transactions, we can re-seek the start: - mork_pos mParser_GroupContentStartPos; // start of this group - - mork_gid mParser_GroupId; // group ID if inside a group - mork_tid mParser_TableId; // table ID if inside a table - mork_rid mParser_RowId; // row ID if inside a row - - mork_bool mParser_InPort; // called OnNewPort but not OnPortEnd? - mork_bool mParser_InDict; // called OnNewDict but not OnDictEnd? - mork_bool mParser_InCell; // called OnNewCell but not OnCellEnd? - mork_bool mParser_InMeta; // called OnNewMeta but not OnMetaEnd? - - mork_bool mParser_InPortRow; // called OnNewPortRow but not OnPortRowEnd? - mork_bool mParser_IsBroken; // has the parse become broken? - mork_bool mParser_IsDone; // has the parse finished? - mork_bool mParser_DoMore; // mParser_MoreGranularity not exhausted? - - mork_change mParser_Change; // driven by modifier in text - - morkAlias mParser_Alias; // current alias being parsed - // note that mParser_Alias.mAlias_Buf points at mParser_ScopeSpool below: - - // blob spools allocated in mParser_Heap - morkSpool mParser_ScopeSpool; // place to accumulate ID scope blobs - morkSpool mParser_ValueSpool; // place to accumulate value blobs - morkSpool mParser_ColumnSpool; // place to accumulate column blobs - morkSpool mParser_StringSpool; // place to accumulate string blobs - - morkSpoolSink mParser_ScopeSink; // writes to mParser_ScopeSpool - morkSpoolSink mParser_ValueSink; // writes to mParser_ValueSpool - morkSpoolSink mParser_ColumnSink; // writes to mParser_ColumnSpool - morkSpoolSink mParser_StringSink; // writes to mParser_StringSpool + mork_u4 mParser_Tag; // must equal morkParser_kTag + mork_count mParser_MoreGranularity; // constructor inBytesPerParseSegment + + mork_u4 mParser_State; // state where parser should resume + + // after finding ends of group transactions, we can re-seek the start: + mork_pos mParser_GroupContentStartPos; // start of this group + + mork_gid mParser_GroupId; // group ID if inside a group + mork_tid mParser_TableId; // table ID if inside a table + mork_rid mParser_RowId; // row ID if inside a row + + mork_bool mParser_InPort; // called OnNewPort but not OnPortEnd? + mork_bool mParser_InDict; // called OnNewDict but not OnDictEnd? + mork_bool mParser_InCell; // called OnNewCell but not OnCellEnd? + mork_bool mParser_InMeta; // called OnNewMeta but not OnMetaEnd? + + mork_bool mParser_InPortRow; // called OnNewPortRow but not OnPortRowEnd? + mork_bool mParser_IsBroken; // has the parse become broken? + mork_bool mParser_IsDone; // has the parse finished? + mork_bool mParser_DoMore; // mParser_MoreGranularity not exhausted? + + mork_change mParser_Change; // driven by modifier in text + + morkAlias mParser_Alias; // current alias being parsed + // note that mParser_Alias.mAlias_Buf points at mParser_ScopeSpool below: + + // blob spools allocated in mParser_Heap + morkSpool mParser_ScopeSpool; // place to accumulate ID scope blobs + morkSpool mParser_ValueSpool; // place to accumulate value blobs + morkSpool mParser_ColumnSpool; // place to accumulate column blobs + morkSpool mParser_StringSpool; // place to accumulate string blobs + + morkSpoolSink mParser_ScopeSink; // writes to mParser_ScopeSpool + morkSpoolSink mParser_ValueSink; // writes to mParser_ValueSpool + morkSpoolSink mParser_ColumnSink; // writes to mParser_ColumnSpool + morkSpoolSink mParser_StringSink; // writes to mParser_StringSpool + + // yarns allocated in mParser_Heap + morkYarn mParser_AliasYarn; // place to receive from AliasToYarn() - // yarns allocated in mParser_Heap - morkYarn mParser_AliasYarn; // place to receive from AliasToYarn() - // span showing current ongoing file position status: - morkSpan mParser_PortSpan; // span of current db port file - - // various spans denoting nested subspaces inside the file's port span: - morkSpan mParser_GroupSpan; // span of current transaction group - morkSpan mParser_DictSpan; - morkSpan mParser_AliasSpan; - morkSpan mParser_MetaSpan; - morkSpan mParser_TableSpan; - morkSpan mParser_RowSpan; - morkSpan mParser_CellSpan; - morkSpan mParser_ColumnSpan; - morkSpan mParser_SlotSpan; + morkSpan mParser_PortSpan; // span of current db port file + + // various spans denoting nested subspaces inside the file's port span: + morkSpan mParser_GroupSpan; // span of current transaction group + morkSpan mParser_DictSpan; + morkSpan mParser_AliasSpan; + morkSpan mParser_MetaSpan; + morkSpan mParser_TableSpan; + morkSpan mParser_RowSpan; + morkSpan mParser_CellSpan; + morkSpan mParser_ColumnSpan; + morkSpan mParser_SlotSpan; private: // convenience inlines - mork_pos HerePos() const - { return mParser_PortSpan.mSpan_End.mPlace_Pos; } + mork_pos HerePos() const + { return mParser_PortSpan.mSpan_End.mPlace_Pos; } - void SetHerePos(mork_pos inPos) - { mParser_PortSpan.mSpan_End.mPlace_Pos = inPos; } - - void AddLine() - { ++ mParser_PortSpan.mSpan_End.mPlace_Line; } + void SetHerePos(mork_pos inPos) + { mParser_PortSpan.mSpan_End.mPlace_Pos = inPos; } + + void AddLine() + { ++ mParser_PortSpan.mSpan_End.mPlace_Line; } // { ===== begin morkNode interface ===== public: // morkNode virtual methods @@ -353,64 +353,64 @@ public: // out virtual morkParser methods, data flow parser to subclass // mp:Slot ::= OnValue | OnValueAlias | OnRowAlias | OnTableAlias - // Note that in interfaces below, mork_change parameters kAdd and kNil - // both mean about the same thing by default. Only kCut is interesting, - // because this usually means to remove members instead of adding them. + // Note that in interfaces below, mork_change parameters kAdd and kNil + // both mean about the same thing by default. Only kCut is interesting, + // because this usually means to remove members instead of adding them. - virtual void OnNewPort(morkEnv* ev, const morkPlace& inPlace) = 0; - virtual void OnPortGlitch(morkEnv* ev, const morkGlitch& inGlitch) = 0; - virtual void OnPortEnd(morkEnv* ev, const morkSpan& inSpan) = 0; + virtual void OnNewPort(morkEnv* ev, const morkPlace& inPlace) = 0; + virtual void OnPortGlitch(morkEnv* ev, const morkGlitch& inGlitch) = 0; + virtual void OnPortEnd(morkEnv* ev, const morkSpan& inSpan) = 0; - virtual void OnNewGroup(morkEnv* ev, const morkPlace& inPlace, mork_gid inGid) = 0; - virtual void OnGroupGlitch(morkEnv* ev, const morkGlitch& inGlitch) = 0; - virtual void OnGroupCommitEnd(morkEnv* ev, const morkSpan& inSpan) = 0; - virtual void OnGroupAbortEnd(morkEnv* ev, const morkSpan& inSpan) = 0; + virtual void OnNewGroup(morkEnv* ev, const morkPlace& inPlace, mork_gid inGid) = 0; + virtual void OnGroupGlitch(morkEnv* ev, const morkGlitch& inGlitch) = 0; + virtual void OnGroupCommitEnd(morkEnv* ev, const morkSpan& inSpan) = 0; + virtual void OnGroupAbortEnd(morkEnv* ev, const morkSpan& inSpan) = 0; - virtual void OnNewPortRow(morkEnv* ev, const morkPlace& inPlace, - const morkAlias& inAlias, mork_change inChange) = 0; - virtual void OnPortRowGlitch(morkEnv* ev, const morkGlitch& inGlitch) = 0; - virtual void OnPortRowEnd(morkEnv* ev, const morkSpan& inSpan) = 0; + virtual void OnNewPortRow(morkEnv* ev, const morkPlace& inPlace, + const morkAlias& inAlias, mork_change inChange) = 0; + virtual void OnPortRowGlitch(morkEnv* ev, const morkGlitch& inGlitch) = 0; + virtual void OnPortRowEnd(morkEnv* ev, const morkSpan& inSpan) = 0; - virtual void OnNewTable(morkEnv* ev, const morkPlace& inPlace, - const morkAlias& inAlias, mork_change inChange) = 0; - virtual void OnTableGlitch(morkEnv* ev, const morkGlitch& inGlitch) = 0; - virtual void OnTableEnd(morkEnv* ev, const morkSpan& inSpan) = 0; - - virtual void OnNewMeta(morkEnv* ev, const morkPlace& inPlace) = 0; - virtual void OnMetaGlitch(morkEnv* ev, const morkGlitch& inGlitch) = 0; - virtual void OnMetaEnd(morkEnv* ev, const morkSpan& inSpan) = 0; + virtual void OnNewTable(morkEnv* ev, const morkPlace& inPlace, + const morkAlias& inAlias, mork_change inChange) = 0; + virtual void OnTableGlitch(morkEnv* ev, const morkGlitch& inGlitch) = 0; + virtual void OnTableEnd(morkEnv* ev, const morkSpan& inSpan) = 0; + + virtual void OnNewMeta(morkEnv* ev, const morkPlace& inPlace) = 0; + virtual void OnMetaGlitch(morkEnv* ev, const morkGlitch& inGlitch) = 0; + virtual void OnMetaEnd(morkEnv* ev, const morkSpan& inSpan) = 0; - virtual void OnNewRow(morkEnv* ev, const morkPlace& inPlace, - const morkAlias& inAlias, mork_change inChange) = 0; - virtual void OnRowGlitch(morkEnv* ev, const morkGlitch& inGlitch) = 0; - virtual void OnRowEnd(morkEnv* ev, const morkSpan& inSpan) = 0; + virtual void OnNewRow(morkEnv* ev, const morkPlace& inPlace, + const morkAlias& inAlias, mork_change inChange) = 0; + virtual void OnRowGlitch(morkEnv* ev, const morkGlitch& inGlitch) = 0; + virtual void OnRowEnd(morkEnv* ev, const morkSpan& inSpan) = 0; - virtual void OnNewDict(morkEnv* ev, const morkPlace& inPlace) = 0; - virtual void OnDictGlitch(morkEnv* ev, const morkGlitch& inGlitch) = 0; - virtual void OnDictEnd(morkEnv* ev, const morkSpan& inSpan) = 0; + virtual void OnNewDict(morkEnv* ev, const morkPlace& inPlace) = 0; + virtual void OnDictGlitch(morkEnv* ev, const morkGlitch& inGlitch) = 0; + virtual void OnDictEnd(morkEnv* ev, const morkSpan& inSpan) = 0; - virtual void OnAlias(morkEnv* ev, const morkSpan& inSpan, - const morkAlias& inAlias) = 0; + virtual void OnAlias(morkEnv* ev, const morkSpan& inSpan, + const morkAlias& inAlias) = 0; - virtual void OnAliasGlitch(morkEnv* ev, const morkGlitch& inGlitch) = 0; + virtual void OnAliasGlitch(morkEnv* ev, const morkGlitch& inGlitch) = 0; - virtual void OnNewCell(morkEnv* ev, const morkPlace& inPlace, - const morkAlias& inAlias, mork_change inChange) = 0; - virtual void OnCellGlitch(morkEnv* ev, const morkGlitch& inGlitch) = 0; - virtual void OnCellForm(morkEnv* ev, mork_cscode inCharsetFormat) = 0; - virtual void OnCellEnd(morkEnv* ev, const morkSpan& inSpan) = 0; - - virtual void OnValue(morkEnv* ev, const morkSpan& inSpan, - const morkBuf& inBuf) = 0; + virtual void OnNewCell(morkEnv* ev, const morkPlace& inPlace, + const morkAlias& inAlias, mork_change inChange) = 0; + virtual void OnCellGlitch(morkEnv* ev, const morkGlitch& inGlitch) = 0; + virtual void OnCellForm(morkEnv* ev, mork_cscode inCharsetFormat) = 0; + virtual void OnCellEnd(morkEnv* ev, const morkSpan& inSpan) = 0; + + virtual void OnValue(morkEnv* ev, const morkSpan& inSpan, + const morkBuf& inBuf) = 0; - virtual void OnValueAlias(morkEnv* ev, const morkSpan& inSpan, - const morkAlias& inAlias) = 0; + virtual void OnValueAlias(morkEnv* ev, const morkSpan& inSpan, + const morkAlias& inAlias) = 0; - virtual void OnRowAlias(morkEnv* ev, const morkSpan& inSpan, - const morkAlias& inAlias) = 0; + virtual void OnRowAlias(morkEnv* ev, const morkSpan& inSpan, + const morkAlias& inAlias) = 0; - virtual void OnTableAlias(morkEnv* ev, const morkSpan& inSpan, - const morkAlias& inAlias) = 0; + virtual void OnTableAlias(morkEnv* ev, const morkSpan& inSpan, + const morkAlias& inAlias) = 0; // ````` ````` ````` ````` ````` ````` ````` ````` protected: // protected parser helper methods diff --git a/mailnews/db/mork/src/morkRowSpace.cpp b/mailnews/db/mork/src/morkRowSpace.cpp index c3f18ed45e5a..ff7b3bcc32f1 100644 --- a/mailnews/db/mork/src/morkRowSpace.cpp +++ b/mailnews/db/mork/src/morkRowSpace.cpp @@ -327,7 +327,7 @@ morkRowSpace::NewRowWithOid(morkEnv* ev, const mdbOid* inOid) { row->InitRow(ev, inOid, this, /*length*/ 0, pool); - if ( ev->Good() ) + if ( ev->Good() && mRowSpace_Rows.AddRow(ev, row) ) outRow = row; else pool->ZapRow(ev, row); @@ -354,7 +354,7 @@ morkRowSpace::NewRow(morkEnv* ev) { row->InitRow(ev, &oid, this, /*length*/ 0, pool); - if ( ev->Good() ) + if ( ev->Good() && mRowSpace_Rows.AddRow(ev, row) ) outRow = row; else pool->ZapRow(ev, row); diff --git a/mailnews/db/mork/src/morkStream.cpp b/mailnews/db/mork/src/morkStream.cpp index edfe864280e8..e7d33fe4239e 100644 --- a/mailnews/db/mork/src/morkStream.cpp +++ b/mailnews/db/mork/src/morkStream.cpp @@ -156,74 +156,201 @@ morkStream::CloseStream(morkEnv* ev) // called by CloseMorkNode(); // } ===== 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; -void + if ( ev->Good() ) + { + this->PutLineBreak(ev); + if ( ev->Good() ) + { + outLength = inDepth; + if ( inDepth ) + this->Write(ev, morkStream_kSpaces, inDepth); + } + } + 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; + + if ( inDepth > morkStream_kMaxIndentDepth ) + inDepth = morkStream_kMaxIndentDepth; + + this->Putc(ev, inByte); + if ( ev->Good() ) + { + this->PutLineBreak(ev); + if ( ev->Good() ) + { + outLength = inDepth; + if ( inDepth ) + this->Write(ev, morkStream_kSpaces, inDepth); + } + } + 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; + + 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(ev, inString, length); + } + + if ( ev->Good() ) + { + this->PutLineBreak(ev); + if ( ev->Good() ) + { + outLength = inDepth; + if ( inDepth ) + this->Write(ev, morkStream_kSpaces, inDepth); + } + } + return outLength; +} + +mork_size morkStream::PutString(morkEnv* ev, const char* inString) { + mork_size outSize = 0; if ( inString ) { - mork_num length = MORK_STRLEN(inString); - if ( length && ev->Good() ) // any bytes to write? + outSize = MORK_STRLEN(inString); + if ( outSize && ev->Good() ) // any bytes to write? { - this->Write(ev, inString, length); + this->Write(ev, inString, outSize); } } + return outSize; } -void +mork_size morkStream::PutStringThenNewline(morkEnv* ev, const char* inString) + // PutStringThenNewline() returns total number of bytes written. { + mork_size outSize = 0; if ( inString ) { - mork_num length = MORK_STRLEN(inString); - if ( length && ev->Good() ) // any bytes to write? + outSize = MORK_STRLEN(inString); + if ( outSize && ev->Good() ) // any bytes to write? { - this->Write(ev, inString, length); + this->Write(ev, inString, outSize); if ( ev->Good() ) - this->WriteNewlines(ev, /*count*/ 1); + outSize += this->PutLineBreak(ev); } } + return outSize; } -void +mork_size morkStream::PutStringThenNewlineThenSpace(morkEnv* ev, const char* inString) + // PutStringThenNewlineThenSpace() returns total number of bytes written. { + mork_size outSize = 0; if ( inString ) { - mork_num length = MORK_STRLEN(inString); - if ( length && ev->Good() ) // any bytes to write? + outSize = MORK_STRLEN(inString); + if ( outSize && ev->Good() ) // any bytes to write? { - this->Write(ev, inString, length); + this->Write(ev, inString, outSize); if ( ev->Good() ) { - this->WriteNewlines(ev, /*count*/ 1); + outSize += this->PutLineBreak(ev); if ( ev->Good() ) + { this->Putc(ev, ' '); + ++outSize; + } } } } + return outSize; } -void +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() ) - this->WriteNewlines(ev, /*count*/ 1); + outSize += this->PutLineBreak(ev); + return outSize; } -void +mork_size morkStream::PutByteThenNewlineThenSpace(morkEnv* ev, int inByte) + // PutByteThenNewlineThenSpace() returns total number of bytes written. { + mork_size outSize = 1; // one for the following byte this->Putc(ev, inByte); if ( ev->Good() ) { - this->WriteNewlines(ev, /*count*/ 1); + outSize += this->PutLineBreak(ev); if ( ev->Good() ) + { this->Putc(ev, ' '); + ++outSize; + } } + return outSize; } +mork_size +morkStream::PutLineBreak(morkEnv* ev) +{ +#ifdef MORK_MAC + + this->Putc(ev, mork_kCR); + return 1; + +#else +# if defined(MORK_WIN) || defined(MORK_OS2) + + 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 @@ -719,13 +846,9 @@ morkStream::spill_buf(morkEnv* ev) // spill/flush from buffer to file } else { -#ifdef AB_CONFIG_TRACE - this->TraceObject(ev); -#endif /*AB_CONFIG_TRACE*/ - -#ifdef AB_CONFIG_DEBUG - ev->Break("", (long) this); -#endif /*AB_CONFIG_DEBUG*/ +#ifdef MORK_DEBUG + ev->NewWarning("stream:spill:not:dirty"); +#endif /*MORK_DEBUG*/ } } else this->NewFileDownError(ev); diff --git a/mailnews/db/mork/src/morkStream.h b/mailnews/db/mork/src/morkStream.h index b536c9eb677b..464383fcef3f 100644 --- a/mailnews/db/mork/src/morkStream.h +++ b/mailnews/db/mork/src/morkStream.h @@ -63,7 +63,7 @@ **| else branch of the statement calls a function that raises an appropriate **| error to complain about either reading a sink or writing a source. **| -**|| morkStream is a direct clone of mork_Stream from Communicator 4.5's +**|| morkStream is a direct clone of ab_Stream from Communicator 4.5's **| address book code, which in turn was based on the stream class in the **| public domain Mithril programming language. |*/ @@ -164,11 +164,33 @@ public: // public non-poly morkStream methods morkFile* GetStreamContentFile() const { return mStream_ContentFile; } mork_size GetStreamBufferSize() const { return mStream_BufSize; } - void PutString(morkEnv* ev, const char* inString); - void PutStringThenNewline(morkEnv* ev, const char* inString); - void PutStringThenNewlineThenSpace(morkEnv* ev, const char* inString); - void PutByteThenNewline(morkEnv* ev, int inByte); - void PutByteThenNewlineThenSpace(morkEnv* ev, int inByte); + mork_size PutIndent(morkEnv* ev, mork_count inDepth); + // PutIndent() puts a linebreak, and then + // "indents" by inDepth, and returns the line length after indentation. + + mork_size 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 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 PutString(morkEnv* ev, const char* inString); + // PutString() returns the length of the string written. + + mork_size PutStringThenNewline(morkEnv* ev, const char* inString); + // PutStringThenNewline() returns total number of bytes written. + + mork_size PutStringThenNewlineThenSpace(morkEnv* ev, const char* inString); + // PutStringThenNewlineThenSpace() returns total number of bytes written. + + mork_size PutByteThenNewline(morkEnv* ev, int inByte); + // PutByteThenNewline() returns total number of bytes written. + + mork_size PutByteThenNewlineThenSpace(morkEnv* ev, int inByte); + // PutByteThenNewlineThenSpace() returns total number of bytes written. // ````` ````` stdio type methods ````` ````` void Printf(morkEnv* ev, const char* inFormat, ...); @@ -201,6 +223,8 @@ public: // public non-poly morkStream methods else spill_putc(ev, c); } + + mork_size PutLineBreak(morkEnv* ev); public: // typesafe refcounting inlines calling inherited morkNode methods static void SlotWeakStream(morkStream* me, diff --git a/mailnews/db/mork/src/morkWriter.cpp b/mailnews/db/mork/src/morkWriter.cpp index 23a353693bfe..2fc18064c0a0 100644 --- a/mailnews/db/mork/src/morkWriter.cpp +++ b/mailnews/db/mork/src/morkWriter.cpp @@ -120,6 +120,9 @@ morkWriter::morkWriter(morkEnv* ev, const morkUsage& inUsage, , mWriter_TotalCount( morkWriter_kCountNumberOfPhases ) , mWriter_DoneCount( 0 ) + +, mWriter_LineSize( 0 ) +, mWriter_MaxIndent( morkWriter_kMaxIndent ) , mWriter_TableCharset( 0 ) , mWriter_TableAtomScope( 0 ) @@ -150,8 +153,11 @@ morkWriter::morkWriter(morkEnv* ev, const morkUsage& inUsage, , mWriter_RowSpaceTablesIter( ) , mWriter_RowSpaceRowsIter( ) { + mWriter_SafeNameBuf[ 0 ] = 0; + mWriter_SafeNameBuf[ morkWriter_kMaxColumnNameSize * 2 ] = 0; mWriter_ColNameBuf[ 0 ] = 0; mWriter_ColNameBuf[ morkWriter_kMaxColumnNameSize ] = 0; + mdbYarn* y = &mWriter_ColYarn; y->mYarn_Buf = mWriter_ColNameBuf; // where to put col bytes y->mYarn_Fill = 0; // set later by writer @@ -160,6 +166,14 @@ morkWriter::morkWriter(morkEnv* ev, const morkUsage& inUsage, y->mYarn_Form = 0; // set later by writer y->mYarn_Grow = 0; // do not allow buffer growth + y = &mWriter_SafeYarn; + y->mYarn_Buf = mWriter_SafeNameBuf; // where to put col bytes + y->mYarn_Fill = 0; // set later by writer + y->mYarn_Size = morkWriter_kMaxColumnNameSize * 2; // our buf size + y->mYarn_More = 0; // set later by writer + y->mYarn_Form = 0; // set later by writer + y->mYarn_Grow = 0; // do not allow buffer growth + if ( ev->Good() ) { if ( ioSlotHeap && ioFile && ioStore ) @@ -328,20 +342,66 @@ morkWriter::WriteMore(morkEnv* ev) // call until IsWritingDone() is true return ev->Good(); } -void -morkWriter::WriteAtom(morkEnv* ev, const morkAtom* inAtom) -{ - morkBuf buf; // to ref content inside atom +static const char* morkWriter_kHexDigits = "0123456789ABCDEF"; - if ( inAtom->AsBuf(buf) ) +mork_size +morkWriter::WriteYarn(morkEnv* ev, const mdbYarn* inYarn) + // return number of atom bytes written on the current line (which + // implies that escaped line breaks will make the size value smaller + // than the entire yarn's size, since only part goes on a last line). +{ + mork_size outSize = 0; + morkStream* stream = mWriter_Stream; + + const mork_u1* b = (const mork_u1*) inYarn->mYarn_Buf; + if ( b ) { - // actually we need to escape problem characters instead of this: - morkStream* stream = mWriter_Stream; - if ( buf.mBuf_Fill ) // any content to write? - stream->Write(ev, buf.mBuf_Body, buf.mBuf_Fill); + register int c; + mork_fill fill = inYarn->mYarn_Fill; + const mork_u1* end = b + fill; + while ( b < end ) + { + c = *b++; // next byte to print + if ( c < 0x080 && MORK_ISPRINT(c) ) + { + if ( c == ')' && c == '$' && c == '\\' ) + { + stream->Putc(ev, '\\'); + ++outSize; + } + stream->Putc(ev, c); + ++outSize; + } + else + { + outSize += 3; // '$' hex hex + stream->Putc(ev, '$'); + stream->Putc(ev, morkWriter_kHexDigits[ (c >> 4) & 0x0F ]); + stream->Putc(ev, morkWriter_kHexDigits[ c & 0x0F ]); + } + } } + mWriter_LineSize += outSize; + + return outSize; +} + +mork_size +morkWriter::WriteAtom(morkEnv* ev, const morkAtom* inAtom) + // return number of atom bytes written on the current line (which + // implies that escaped line breaks will make the size value smaller + // than the entire atom's size, since only part goes on a last line). +{ + mork_size outSize = 0; + mdbYarn yarn; // to ref content inside atom + + if ( inAtom->AliasYarn(&yarn) ) + outSize = this->WriteYarn(ev, &yarn); + // mWriter_LineSize += stream->Write(ev, inYarn->mYarn_Buf, outSize); else inAtom->BadAtomKindError(ev); + + return outSize; } void @@ -351,10 +411,13 @@ morkWriter::WriteAtomSpaceAsDict(morkEnv* ev, morkAtomSpace* ioSpace) mork_scope scope = ioSpace->mSpace_Scope; if ( scope < 0x80 ) { - stream->WriteNewlines(ev, /*count*/ 1); - stream->PutString(ev, "<<(atomScope="); + if ( mWriter_LineSize ) + stream->PutLineBreak(ev); + stream->PutString(ev, "< <(atomScope="); stream->Putc(ev, (int) scope); - stream->PutStringThenNewline(ev, ")> // (charset=iso-8859-1)"); + ++mWriter_LineSize; + stream->PutString(ev, ")> // (charset=iso-8859-1)"); + mWriter_LineSize = stream->PutIndent(ev, morkWriter_kDictAliasDepth); } else ioSpace->NonAsciiSpaceScopeName(ev); @@ -379,11 +442,18 @@ morkWriter::WriteAtomSpaceAsDict(morkEnv* ev, morkAtomSpace* ioSpace) { atom->mAtom_Change = morkChange_kNil; // neutralize change + this->IndentAsNeeded(ev, morkWriter_kDictAliasDepth); mork_size size = ev->TokenAsHex(idBuf, atom->mBookAtom_Id); - idBuf[ size ] = '='; - stream->Write(ev, buf, size+2); // plus two for '(' and '=' + mWriter_LineSize += stream->Write(ev, buf, size+1); // '(' + + this->IndentAsNeeded(ev, morkWriter_kDictAliasValueDepth); + stream->Putc(ev, '='); // end alias + ++mWriter_LineSize; + this->WriteAtom(ev, atom); - stream->PutByteThenNewlineThenSpace(ev, ')'); // end alias + stream->Putc(ev, ')'); // end alias + ++mWriter_LineSize; + ++mWriter_DoneCount; } else // temporarily warn about wrong change slot value @@ -396,7 +466,10 @@ morkWriter::WriteAtomSpaceAsDict(morkEnv* ev, morkAtomSpace* ioSpace) } if ( ev->Good() ) + { + this->IndentAsNeeded(ev, 0); stream->PutByteThenNewline(ev, '>'); // end dict + } } mork_bool @@ -556,6 +629,7 @@ morkWriter::OnDirtyAllDone(morkEnv* ev) if ( ev->Good() ) { stream->PutStringThenNewline(ev, "// "); + mWriter_LineSize = 0; } if ( ev->Good() ) @@ -570,8 +644,10 @@ mork_bool morkWriter::OnPutHeaderDone(morkEnv* ev) { morkStream* stream = mWriter_Stream; - stream->WriteNewlines(ev, /*count*/ 1); + if ( mWriter_LineSize ) + stream->PutLineBreak(ev); stream->PutStringThenNewline(ev, "// OnPutHeaderDone()"); + mWriter_LineSize = 0; morkStore* store = mWriter_Store; if ( store ) @@ -591,8 +667,10 @@ mork_bool morkWriter::OnRenumberAllDone(morkEnv* ev) { morkStream* stream = mWriter_Stream; - stream->WriteNewlines(ev, /*count*/ 1); + if ( mWriter_LineSize ) + stream->PutLineBreak(ev); stream->PutStringThenNewline(ev, "// OnRenumberAllDone()"); + mWriter_LineSize = 0; if ( ev->Good() ) mWriter_Phase = morkWriter_kPhaseStoreAtomSpaces; @@ -606,8 +684,10 @@ mork_bool morkWriter::OnStoreAtomSpaces(morkEnv* ev) { morkStream* stream = mWriter_Stream; - stream->WriteNewlines(ev, /*count*/ 1); + if ( mWriter_LineSize ) + stream->PutLineBreak(ev); stream->PutStringThenNewline(ev, "// OnStoreAtomSpaces()"); + mWriter_LineSize = 0; if ( ev->Good() ) { @@ -618,6 +698,7 @@ morkWriter::OnStoreAtomSpaces(morkEnv* ev) if ( space ) { stream->PutStringThenNewline(ev, "// ground column space dict:"); + mWriter_LineSize = 0; this->WriteAtomSpaceAsDict(ev, space); } } @@ -637,8 +718,10 @@ mork_bool morkWriter::OnAtomSpaceAtomAids(morkEnv* ev) { morkStream* stream = mWriter_Stream; - stream->WriteNewlines(ev, /*count*/ 1); + if ( mWriter_LineSize ) + stream->PutLineBreak(ev); stream->PutStringThenNewline(ev, "// OnAtomSpaceAtomAids()"); + mWriter_LineSize = 0; if ( ev->Good() ) mWriter_Phase = morkWriter_kPhaseStoreRowSpacesTables; @@ -711,8 +794,10 @@ mork_bool morkWriter::OnStoreRowSpacesTables(morkEnv* ev) { morkStream* stream = mWriter_Stream; - stream->WriteNewlines(ev, /*count*/ 1); + if ( mWriter_LineSize ) + stream->PutLineBreak(ev); stream->PutStringThenNewline(ev, "// OnStoreRowSpacesTables()"); + mWriter_LineSize = 0; // later we'll break this up, but today we'll write all in one shot: this->WriteAllStoreTables(ev); @@ -729,8 +814,10 @@ mork_bool morkWriter::OnRowSpaceTables(morkEnv* ev) { morkStream* stream = mWriter_Stream; - stream->WriteNewlines(ev, /*count*/ 1); + if ( mWriter_LineSize ) + stream->PutLineBreak(ev); stream->PutStringThenNewline(ev, "// OnRowSpaceTables()"); + mWriter_LineSize = 0; if ( ev->Good() ) mWriter_Phase = morkWriter_kPhaseStoreRowSpacesRows; @@ -744,8 +831,10 @@ mork_bool morkWriter::OnTableRowArray(morkEnv* ev) { morkStream* stream = mWriter_Stream; - stream->WriteNewlines(ev, /*count*/ 1); + if ( mWriter_LineSize ) + stream->PutLineBreak(ev); stream->PutStringThenNewline(ev, "// OnTableRowArray()"); + mWriter_LineSize = 0; if ( ev->Good() ) mWriter_Phase = morkWriter_kPhaseStoreRowSpacesRows; @@ -759,8 +848,10 @@ mork_bool morkWriter::OnStoreRowSpacesRows(morkEnv* ev) { morkStream* stream = mWriter_Stream; - stream->WriteNewlines(ev, /*count*/ 1); + if ( mWriter_LineSize ) + stream->PutLineBreak(ev); stream->PutStringThenNewline(ev, "// OnStoreRowSpacesRows()"); + mWriter_LineSize = 0; if ( ev->Good() ) mWriter_Phase = morkWriter_kPhaseContentDone; @@ -774,8 +865,10 @@ mork_bool morkWriter::OnRowSpaceRows(morkEnv* ev) { morkStream* stream = mWriter_Stream; - stream->WriteNewlines(ev, /*count*/ 1); + if ( mWriter_LineSize ) + stream->PutLineBreak(ev); stream->PutStringThenNewline(ev, "// OnRowSpaceRows()"); + mWriter_LineSize = 0; if ( ev->Good() ) mWriter_Phase = morkWriter_kPhaseContentDone; @@ -789,8 +882,10 @@ mork_bool morkWriter::OnContentDone(morkEnv* ev) { morkStream* stream = mWriter_Stream; - stream->WriteNewlines(ev, /*count*/ 1); + if ( mWriter_LineSize ) + stream->PutLineBreak(ev); stream->PutStringThenNewline(ev, "// OnContentDone()"); + mWriter_LineSize = 0; stream->Flush(ev); morkFile* bud = mWriter_Bud; if ( bud ) @@ -820,7 +915,7 @@ mork_bool morkWriter::PutTable(morkEnv* ev, morkTable* ioTable) { if ( ev->Good() ) - this->StartTable(ev, ioTable->mTable_Id); + this->StartTable(ev, ioTable); if ( ev->Good() ) { @@ -904,13 +999,21 @@ morkWriter::WriteTokenToTokenMetaCell(morkEnv* ev, *p++ = '^'; // indicates col is hex ID mork_size colSize = ev->TokenAsHex(p, inCol); - p += colSize; // advance past the col in hex - *p++ = ' '; // space between hex IDs - *p++ = '^'; // indicates value is hex ID - mork_size valSize = ev->TokenAsHex(p, inValue); - p += valSize; // advance past the value in hex - *p = ')'; - stream->Write(ev, buf, colSize + valSize + 5); + p += colSize; + *p++ = '='; // we always start with open paren + mWriter_LineSize += stream->Write(ev, buf, colSize + 3); + + this->IndentAsNeeded(ev, morkWriter_kTableMetaCellValueDepth); + mdbYarn* yarn = &mWriter_ColYarn; + // mork_u1* yarnBuf = (mork_u1*) yarn->mYarn_Buf; + mWriter_Store->TokenToString(ev, inValue, yarn); + this->WriteYarn(ev, yarn); + stream->Putc(ev, ')'); + ++mWriter_LineSize; + + // mork_fill fill = yarn->mYarn_Fill; + // yarnBuf[ fill ] = ')'; // append terminator + // mWriter_LineSize += stream->Write(ev, yarnBuf, fill + 1); // +1 for ')' } void @@ -918,14 +1021,20 @@ morkWriter::WriteStringToTokenDictCell(morkEnv* ev, const char* inCol, mork_token inValue) // Note inCol should begin with '(' and end with '=', with col in between. { - mdbYarn* yarn = &mWriter_ColYarn; - mork_u1* yarnBuf = (mork_u1*) yarn->mYarn_Buf; morkStream* stream = mWriter_Stream; - stream->PutString(ev, inCol); + mWriter_LineSize += stream->PutString(ev, inCol); + + this->IndentAsNeeded(ev, morkWriter_kDictMetaCellValueDepth); + mdbYarn* yarn = &mWriter_ColYarn; + // mork_u1* yarnBuf = (mork_u1*) yarn->mYarn_Buf; mWriter_Store->TokenToString(ev, inValue, yarn); - mork_fill fill = yarn->mYarn_Fill; - yarnBuf[ fill ] = ')'; // append terminator - stream->Write(ev, yarnBuf, fill + 1); // plus one for ')' + this->WriteYarn(ev, yarn); + stream->Putc(ev, ')'); + ++mWriter_LineSize; + + // mork_fill fill = yarn->mYarn_Fill; + // yarnBuf[ fill ] = ')'; // append terminator + // mWriter_LineSize += stream->Write(ev, yarnBuf, fill + 1); // +1 for ')' } void @@ -934,28 +1043,35 @@ morkWriter::StartDict(morkEnv* ev) morkStream* stream = mWriter_Stream; if ( mWriter_DidStartDict ) { - stream->WriteNewlines(ev, /*count*/ 1); + if ( mWriter_LineSize ) + stream->PutLineBreak(ev); stream->PutStringThenNewline(ev, "> // end dict"); + mWriter_LineSize = 0; } mWriter_DidStartDict = morkBool_kTrue; - stream->WriteNewlines(ev, /*count*/ 1); + if ( mWriter_LineSize ) + stream->PutLineBreak(ev); + mWriter_LineSize = 0; if ( mWriter_DictCharset || mWriter_DictAtomScope != 'a' ) { stream->Putc(ev, '<'); + stream->Putc(ev, ' '); stream->Putc(ev, '<'); + mWriter_LineSize = 3; if ( mWriter_DictCharset ) this->WriteStringToTokenDictCell(ev, "(charset=", mWriter_DictCharset); if ( mWriter_DictAtomScope != 'a' ) this->WriteStringToTokenDictCell(ev, "(atomScope=", mWriter_DictAtomScope); - stream->PutByteThenNewlineThenSpace(ev, '>'); + stream->Putc(ev, '>'); + ++mWriter_LineSize; } else { - stream->PutStringThenNewlineThenSpace(ev, - "< // <(charset=iso-8859-1)(atomScope=a)>"); + stream->PutString(ev, "< // <(charset=iso-8859-1)(atomScope=a)>"); } + mWriter_LineSize = stream->PutIndent(ev, morkWriter_kDictAliasDepth); } void @@ -964,45 +1080,63 @@ morkWriter::EndDict(morkEnv* ev) morkStream* stream = mWriter_Stream; if ( mWriter_DidStartDict ) { - stream->WriteNewlines(ev, /*count*/ 1); + if ( mWriter_LineSize ) + stream->PutLineBreak(ev); stream->PutStringThenNewline(ev, "> // end dict"); + mWriter_LineSize = 0; } mWriter_DidStartDict = morkBool_kFalse; } void -morkWriter::StartTable(morkEnv* ev, mork_tid inTid) +morkWriter::StartTable(morkEnv* ev, morkTable* ioTable) { - morkStream* stream = mWriter_Stream; - stream->WriteNewlines(ev, /*count*/ 1); - - char buf[ 64 ]; // buffer for staging hex - char* p = buf; - *p++ = '{'; - mork_size size = ev->TokenAsHex(p, inTid); - p += size; - *p++ = ' '; - *p = '{'; - stream->Write(ev, buf, size + 3); + mdbOid toid; // to receive table oid + ioTable->GetTableOid(ev, &toid); - morkStore* store = mWriter_Store; - mork_scope rs = mWriter_TableRowScope; - if ( rs ) - this->WriteTokenToTokenMetaCell(ev, store->mStore_RowScopeToken, rs); - - mork_kind tk = mWriter_TableKind; - if ( tk ) - this->WriteTokenToTokenMetaCell(ev, store->mStore_TableKindToken, tk); + if ( ev->Good() ) + { + morkStream* stream = mWriter_Stream; + if ( mWriter_LineSize ) + stream->PutLineBreak(ev); + mWriter_LineSize = 0; - stream->PutByteThenNewlineThenSpace(ev, '}'); + char buf[ 64 ]; // buffer for staging hex + char* p = buf; + *p++ = '{'; + mork_size size = ev->OidAsHex(p, toid); + p += size; + *p++ = ' '; + *p = '{'; + mWriter_LineSize += stream->Write(ev, buf, size + 3); + + morkStore* store = mWriter_Store; + mork_scope rs = mWriter_TableRowScope; + if ( rs ) + { + this->IndentAsNeeded(ev, morkWriter_kTableMetaCellDepth); + this->WriteTokenToTokenMetaCell(ev, store->mStore_RowScopeToken, rs); + } + mork_kind tk = mWriter_TableKind; + if ( tk ) + { + this->IndentAsNeeded(ev, morkWriter_kTableMetaCellDepth); + this->WriteTokenToTokenMetaCell(ev, store->mStore_TableKindToken, tk); + } + stream->Putc(ev, '}'); + stream->Putc(ev, ' '); + mWriter_LineSize += 2; + } } void morkWriter::EndTable(morkEnv* ev) { morkStream* stream = mWriter_Stream; - stream->WriteNewlines(ev, /*count*/ 1); + if ( mWriter_LineSize ) + stream->PutLineBreak(ev); stream->PutStringThenNewline(ev, "} // end table"); + mWriter_LineSize = 0; } mork_bool @@ -1018,7 +1152,7 @@ morkWriter::PutRowDict(morkEnv* ev, morkRow* ioRow) morkCell* end = cells + ioRow->mRow_Length; --cells; // prepare for preincrement: - while ( ++cells < end ) + while ( ++cells < end && ev->Good() ) { morkAtom* atom = cells->GetAtom(); if ( atom && atom->mAtom_Change == morkChange_kAdd ) @@ -1027,12 +1161,19 @@ morkWriter::PutRowDict(morkEnv* ev, morkRow* ioRow) { atom->mAtom_Change = morkChange_kNil; // neutralize change + this->IndentAsNeeded(ev, morkWriter_kDictAliasDepth); morkBookAtom* ba = (morkBookAtom*) atom; mork_size size = ev->TokenAsHex(idBuf, ba->mBookAtom_Id); - idBuf[ size ] = '='; - stream->Write(ev, buf, size+2); // plus two for '(' and '=' + mWriter_LineSize += stream->Write(ev, buf, size+1); // '(' + + this->IndentAsNeeded(ev, morkWriter_kDictAliasValueDepth); + stream->Putc(ev, '='); // start value + ++mWriter_LineSize; + this->WriteAtom(ev, atom); - stream->PutByteThenNewlineThenSpace(ev, ')'); // end alias + stream->Putc(ev, ')'); // end alias + ++mWriter_LineSize; + ++mWriter_DoneCount; } } @@ -1067,17 +1208,16 @@ morkWriter::PutRowCells(morkEnv* ev, morkRow* ioRow) colSize = ev->TokenAsHex(p, col); p += colSize; + this->IndentAsNeeded(ev, morkWriter_kRowCellDepth); if ( atom->IsBook() ) // is it possible to write atom ID? { - *p++ = ' '; *p++ = '^'; morkBookAtom* ba = (morkBookAtom*) atom; mork_size valSize = ev->TokenAsHex(p, ba->mBookAtom_Id); p += valSize; *p = ')'; - stream->Write(ev, buf, colSize + valSize + 5); - stream->WriteNewlines(ev, /*count*/ 1); - stream->Putc(ev, ' '); + + mWriter_LineSize += stream->Write(ev, buf, colSize + valSize + 4); if ( atom->mAtom_Change == morkChange_kAdd ) { @@ -1087,10 +1227,15 @@ morkWriter::PutRowCells(morkEnv* ev, morkRow* ioRow) } else // must write an anonymous atom { - *p++ = '='; - stream->Write(ev, buf, colSize + 3); + mWriter_LineSize += stream->Write(ev, buf, colSize + 2); + + this->IndentAsNeeded(ev, morkWriter_kRowCellValueDepth); + stream->Putc(ev, '='); + ++mWriter_LineSize; + this->WriteAtom(ev, atom); - stream->PutByteThenNewlineThenSpace(ev, ')'); // end alias + stream->Putc(ev, ')'); // end alias + ++mWriter_LineSize; } } } @@ -1107,7 +1252,10 @@ morkWriter::PutRow(morkEnv* ev, morkRow* ioRow) mdbOid* roid = &ioRow->mRow_Oid; mork_size ridSize = 0; - if ( ioRow->IsRowDirty() ) + this->IndentAsNeeded(ev, morkWriter_kRowDepth); + + // if ( ioRow->IsRowDirty() ) + if ( morkBool_kTrue ) { ioRow->SetRowClean(); mork_rid rid = roid->mOid_Id; @@ -1119,10 +1267,12 @@ morkWriter::PutRow(morkEnv* ev, morkRow* ioRow) p += ridSize; *p++ = ' '; - stream->Write(ev, buf, ridSize + 2); + mWriter_LineSize += stream->Write(ev, buf, ridSize + 2); this->PutRowCells(ev, ioRow); - stream->PutByteThenNewlineThenSpace(ev, ']'); // end row + stream->Putc(ev, ']'); // end row + stream->Putc(ev, ' '); // end row + mWriter_LineSize += 2; } else { @@ -1131,9 +1281,9 @@ morkWriter::PutRow(morkEnv* ev, morkRow* ioRow) else ridSize = ev->OidAsHex(p, *roid); - stream->Write(ev, buf, ridSize); - stream->WriteNewlines(ev, /*count*/ 1); + mWriter_LineSize += stream->Write(ev, buf, ridSize); stream->Putc(ev, ' '); + ++mWriter_LineSize; } ++mWriter_DoneCount; diff --git a/mailnews/db/mork/src/morkWriter.h b/mailnews/db/mork/src/morkWriter.h index c2cb8d4ce6fc..51c79bfd74b5 100644 --- a/mailnews/db/mork/src/morkWriter.h +++ b/mailnews/db/mork/src/morkWriter.h @@ -51,6 +51,10 @@ #include "morkRowSpace.h" #endif +#ifndef _MORKSTREAM_ +#include "morkStream.h" +#endif + //3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789 @@ -79,7 +83,22 @@ #define morkWriter_kCountNumberOfPhases 13 /* part of mWrite_TotalCount */ -#define morkWriter_kMaxColumnNameSize 256 /* longest writable col name */ +#define morkWriter_kMaxColumnNameSize 128 /* longest writable col name */ + +#define morkWriter_kMaxIndent 48 /* default value for mWriter_MaxIndent */ + +#define morkWriter_kTableMetaCellDepth 4 /* */ +#define morkWriter_kTableMetaCellValueDepth 6 /* */ + +#define morkWriter_kDictMetaCellDepth 4 /* */ +#define morkWriter_kDictMetaCellValueDepth 6 /* */ + +#define morkWriter_kDictAliasDepth 2 /* */ +#define morkWriter_kDictAliasValueDepth 4 /* */ + +#define morkWriter_kRowDepth 2 /* */ +#define morkWriter_kRowCellDepth 4 /* */ +#define morkWriter_kRowCellValueDepth 6 /* */ class morkWriter : public morkNode { // row iterator @@ -105,6 +124,9 @@ public: // state is public because the entire Mork system is private mork_count mWriter_TotalCount; // count of all things to be written mork_count mWriter_DoneCount; // count of things already written + mork_size mWriter_LineSize; // length of current line being written + mork_size mWriter_MaxIndent; // line size forcing a line break + mork_cscode mWriter_TableCharset; // current charset metainfo mork_scope mWriter_TableAtomScope; // current atom scope mork_scope mWriter_TableRowScope; // current row scope @@ -125,12 +147,18 @@ public: // state is public because the entire Mork system is private mork_bool mWriter_DidEndDict; // true when a dict has been ended mork_pos mWriter_TableRowArrayPos; // index into mTable_RowArray - + + char mWriter_SafeNameBuf[ (morkWriter_kMaxColumnNameSize * 2) + 4 ]; + // Note: extra four bytes in ColNameBuf means we can always append to yarn + char mWriter_ColNameBuf[ morkWriter_kMaxColumnNameSize + 4 ]; // Note: extra four bytes in ColNameBuf means we can always append to yarn mdbYarn mWriter_ColYarn; // a yarn to describe space in ColNameBuf: // mYarn_Buf == mWriter_ColNameBuf, mYarn_Size == morkWriter_kMaxColumnNameSize + + mdbYarn mWriter_SafeYarn; // a yarn to describe space in ColNameBuf: + // mYarn_Buf == mWriter_SafeNameBuf, mYarn_Size == (kMaxColumnNameSize * 2) morkAtomSpaceMapIter mWriter_StoreAtomSpacesIter; // for mStore_AtomSpaces morkAtomAidMapIter mWriter_AtomSpaceAtomAidsIter; // for AtomSpace_AtomAids @@ -169,6 +197,15 @@ public: // typing & errors public: // inlines mork_bool DidStartDict() const { return mWriter_DidStartDict; } mork_bool DidEndDict() const { return mWriter_DidEndDict; } + + mork_bool NeedLineBreak() const + { return ( mWriter_LineSize > mWriter_MaxIndent ); } + + void IndentAsNeeded(morkEnv* ev, mork_size inDepth) + { + if ( mWriter_LineSize > mWriter_MaxIndent ) + mWriter_LineSize = mWriter_Stream->PutIndent(ev, inDepth); + } public: // iterative/asynchronouse writing @@ -220,8 +257,17 @@ public: // writing node content second pass public: // other writer methods + mork_size WriteYarn(morkEnv* ev, const mdbYarn* inYarn); + // return number of atom bytes written on the current line (which + // implies that escaped line breaks will make the size value smaller + // than the entire yarn's size, since only part goes on a last line). + + mork_size WriteAtom(morkEnv* ev, const morkAtom* inAtom); + // return number of atom bytes written on the current line (which + // implies that escaped line breaks will make the size value smaller + // than the entire atom's size, since only part goes on a last line). + void WriteAllStoreTables(morkEnv* ev); - void WriteAtom(morkEnv* ev, const morkAtom* inAtom); void WriteAtomSpaceAsDict(morkEnv* ev, morkAtomSpace* ioSpace); void WriteTokenToTokenMetaCell(morkEnv* ev, mork_token inCol, @@ -233,7 +279,7 @@ public: // other writer methods void StartDict(morkEnv* ev); void EndDict(morkEnv* ev); - void StartTable(morkEnv* ev, mork_tid inTid); + void StartTable(morkEnv* ev, morkTable* ioTable); void EndTable(morkEnv* ev); public: // typesafe refcounting inlines calling inherited morkNode methods