latest mork drop, fix commit code

This commit is contained in:
bienvenu%netscape.com 1999-03-15 01:32:31 +00:00
parent 06d478946f
commit 2e5950d728
20 changed files with 1200 additions and 466 deletions

View File

@ -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)

View File

@ -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;

View File

@ -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,

View File

@ -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();

View File

@ -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

View File

@ -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);

View File

@ -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("<ab:stream:spill:not:dirty me=\"^%lX\"/>", (long) this);
#endif /*AB_CONFIG_DEBUG*/
#ifdef MORK_DEBUG
ev->NewWarning("stream:spill:not:dirty");
#endif /*MORK_DEBUG*/
}
}
else this->NewFileDownError(ev);

View File

@ -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,

View File

@ -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, "// <!-- <mdb:mork:z v=\"1.1\"/> -->");
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;

View File

@ -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

View File

@ -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)

View File

@ -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;

View File

@ -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,

View File

@ -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();

View File

@ -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

View File

@ -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);

View File

@ -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("<ab:stream:spill:not:dirty me=\"^%lX\"/>", (long) this);
#endif /*AB_CONFIG_DEBUG*/
#ifdef MORK_DEBUG
ev->NewWarning("stream:spill:not:dirty");
#endif /*MORK_DEBUG*/
}
}
else this->NewFileDownError(ev);

View File

@ -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,

View File

@ -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, "// <!-- <mdb:mork:z v=\"1.1\"/> -->");
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;

View File

@ -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