Back to index

lightning-sunbird  0.9+nobinonly
morkSink.h
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-  */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1999
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either of the GNU General Public License Version 2 or later (the "GPL"),
00026  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 #ifndef _MORKSINK_
00039 #define _MORKSINK_ 1
00040 
00041 #ifndef _MORK_
00042 #include "mork.h"
00043 #endif
00044 
00045 #ifndef _MORKBLOB_
00046 #include "morkBlob.h"
00047 #endif
00048 
00049 //3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
00050 
00051 /*| morkSink is intended to be a very cheap buffered i/o sink which
00052 **| writes to bufs and other strings a single byte at a time.  The
00053 **| basic idea is that writing a single byte has a very cheap average
00054 **| cost, because a polymophic function call need only occur when the
00055 **| space between At and End is exhausted.  The rest of the time a
00056 **| very cheap inline method will write a byte, and then bump a pointer.
00057 **|
00058 **|| At: the current position in some sequence of bytes at which to
00059 **| write the next byte put into the sink.  Presumably At points into
00060 **| the private storage of some space which is not yet filled (except
00061 **| when At reaches End, and the overflow must then spill).  Note both
00062 **| At and End are zeroed in the destructor to help show that a sink
00063 **| is no longer usable; this is safe because At==End causes the case
00064 **| where SpillPutc() is called to handled an exhausted buffer space.
00065 **|
00066 **|| End: an address one byte past the last byte which can be written
00067 **| without needing to make a buffer larger than previously.  When At
00068 **| and End are equal, this means there is no space to write a byte,
00069 **| and that some underlying buffer space must be grown before another
00070 **| byte can be written.  Note At must always be less than or equal to
00071 **| End, and otherwise an important invariant has failed severely.
00072 **|
00073 **|| Buf: this original class slot has been commented out in the new
00074 **| and more abstract version of this sink class, but the general idea
00075 **| behind this slot should be explained to help design subclasses.
00076 **| Each subclass should provide space into which At and End can point,
00077 **| where End is beyond the last writable byte, and At is less than or
00078 **| equal to this point inside the same buffer.  With some kinds of
00079 **| medium, such as writing to an instance of morkBlob, it is feasible
00080 **| to point directly into the final resting place for all the content
00081 **| written to the medium.  Other mediums such as files, which write
00082 **| only through function calls, will typically need a local buffer
00083 **| to efficiently accumulate many bytes between such function calls.
00084 **|
00085 **|| FlushSink: this flush method should move any buffered content to 
00086 **| it's final destination.  For example, for buffered writes to a
00087 **| string medium, where string methods are function calls and not just
00088 **| inline macros, it is faster to accumulate many bytes in a small
00089 **| local buffer and then move these en masse later in a single call.
00090 **|
00091 **|| SpillPutc: when At is greater than or equal to End, this means an
00092 **| underlying buffer has become full, so the buffer must be flushed
00093 **| before a new byte can be written.  The intention is that SpillPutc()
00094 **| will be equivalent to calling FlushSink() followed by another call
00095 **| to Putc(), where the flush is expected to make At less then End once
00096 **| again.  Except that FlushSink() need not make the underlying buffer
00097 **| any larger, and SpillPutc() typically must make room for more bytes.
00098 **| Note subclasses might want to guard against the case that both At
00099 **| and End are null, which happens when a sink is destroyed, which sets
00100 **| both these pointers to null as an indication the sink is disabled.
00101 |*/
00102 class morkSink {
00103     
00104 // ````` ````` ````` `````   ````` ````` ````` `````  
00105 public: // public sink virtual methods
00106 
00107   virtual void FlushSink(morkEnv* ev) = 0;
00108   virtual void SpillPutc(morkEnv* ev, int c) = 0;
00109 
00110 // ````` ````` ````` `````   ````` ````` ````` `````  
00111 public: // member variables
00112 
00113   mork_u1*     mSink_At;     // pointer into mSink_Buf
00114   mork_u1*     mSink_End;    // one byte past last content byte
00115 
00116 // define morkSink_kBufSize 256 /* small enough to go on stack */
00117 
00118   // mork_u1      mSink_Buf[ morkSink_kBufSize + 4 ];
00119   // want plus one for any needed end null byte; use plus 4 for alignment
00120    
00121 // ````` ````` ````` `````   ````` ````` ````` `````  
00122 public: // public non-poly morkSink methods
00123 
00124   virtual ~morkSink(); // zero both At and End; virtual for subclasses
00125   morkSink() { } // does nothing; subclasses must set At and End suitably
00126 
00127   void Putc(morkEnv* ev, int c)
00128   { 
00129     if ( mSink_At < mSink_End )
00130       *mSink_At++ = (mork_u1) c;
00131     else
00132       this->SpillPutc(ev, c);
00133   }
00134 };
00135 
00136 /*| morkSpool: an output sink that efficiently writes individual bytes
00137 **| or entire byte sequences to a coil instance, which grows as needed by
00138 **| using the heap instance in the coil to grow the internal buffer.
00139 **|
00140 **|| Note we do not "own" the coil referenced by mSpool_Coil, and
00141 **| the lifetime of the coil is expected to equal or exceed that of this
00142 **| sink by some external means.  Typical usage might involve keeping an
00143 **| instance of morkCoil and an instance of morkSpool in the same
00144 **| owning parent object, which uses the spool with the associated coil.
00145 |*/
00146 class morkSpool : public morkSink { // for buffered i/o to a morkCoil
00147 
00148 // ````` ````` ````` `````   ````` ````` ````` `````  
00149 public: // public sink virtual methods
00150 
00151   // when morkSink::Putc() moves mSink_At, mSpool_Coil->mBuf_Fill is wrong:
00152 
00153   virtual void FlushSink(morkEnv* ev); // sync mSpool_Coil->mBuf_Fill
00154   virtual void SpillPutc(morkEnv* ev, int c); // grow coil and write byte
00155 
00156 // ````` ````` ````` `````   ````` ````` ````` `````  
00157 public: // member variables
00158   morkCoil*   mSpool_Coil; // destination medium for written bytes
00159     
00160 // ````` ````` ````` `````   ````` ````` ````` `````  
00161 public: // public non-poly morkSink methods
00162 
00163   static void BadSpoolCursorOrderError(morkEnv* ev);
00164   static void NilSpoolCoilError(morkEnv* ev);
00165 
00166   virtual ~morkSpool();
00167   // Zero all slots to show this sink is disabled, but destroy no memory.
00168   // Note it is typically unnecessary to flush this coil sink, since all
00169   // content is written directly to the coil without any buffering.
00170   
00171   morkSpool(morkEnv* ev, morkCoil* ioCoil);
00172   // After installing the coil, calls Seek(ev, 0) to prepare for writing.
00173   
00174   // ----- All boolean return values below are equal to ev->Good(): -----
00175 
00176   mork_bool Seek(morkEnv* ev, mork_pos inPos);
00177   // Changed the current write position in coil's buffer to inPos.
00178   // For example, to start writing the coil from scratch, use inPos==0.
00179 
00180   mork_bool Write(morkEnv* ev, const void* inBuf, mork_size inSize);
00181   // write inSize bytes of inBuf to current position inside coil's buffer
00182 
00183   mork_bool PutBuf(morkEnv* ev, const morkBuf& inBuffer)
00184   { return this->Write(ev, inBuffer.mBuf_Body, inBuffer.mBuf_Fill); }
00185   
00186   mork_bool PutString(morkEnv* ev, const char* inString);
00187   // call Write() with inBuf=inString and inSize=strlen(inString),
00188   // unless inString is null, in which case we then do nothing at all.
00189 };
00190 
00191 //3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
00192 
00193 #endif /* _MORKSINK_ */