Back to index

lightning-sunbird  0.9+nobinonly
morkAtom.cpp
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 _MDB_
00039 #include "mdb.h"
00040 #endif
00041 
00042 #ifndef _MORK_
00043 #include "mork.h"
00044 #endif
00045 
00046 #ifndef _MORKBLOB_
00047 #include "morkBlob.h"
00048 #endif
00049 
00050 #ifndef _MORKATOM_
00051 #include "morkAtom.h"
00052 #endif
00053 
00054 #ifndef _MORKENV_
00055 #include "morkEnv.h"
00056 #endif
00057 
00058 #ifndef _MORKATOMSPACE_
00059 #include "morkAtomSpace.h"
00060 #endif
00061 
00062 //3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
00063 
00064 mork_bool
00065 morkAtom::GetYarn(mdbYarn* outYarn) const
00066 {
00067   const void* source = 0;  
00068   mdb_fill fill = 0; 
00069   mdb_cscode form = 0;
00070   outYarn->mYarn_More = 0;
00071 
00072   if ( this )
00073   {
00074     if ( this->IsWeeBook() )
00075     {
00076       morkWeeBookAtom* weeBook = (morkWeeBookAtom*) this;
00077       source = weeBook->mWeeBookAtom_Body;
00078       fill = weeBook->mAtom_Size;
00079     }
00080     else if ( this->IsBigBook() )
00081     {
00082       morkBigBookAtom* bigBook = (morkBigBookAtom*) this;
00083       source = bigBook->mBigBookAtom_Body;
00084       fill = bigBook->mBigBookAtom_Size;
00085       form = bigBook->mBigBookAtom_Form;
00086     }
00087     else if ( this->IsWeeAnon() )
00088     {
00089       morkWeeAnonAtom* weeAnon = (morkWeeAnonAtom*) this;
00090       source = weeAnon->mWeeAnonAtom_Body;
00091       fill = weeAnon->mAtom_Size;
00092     }
00093     else if ( this->IsBigAnon() )
00094     {
00095       morkBigAnonAtom* bigAnon = (morkBigAnonAtom*) this;
00096       source = bigAnon->mBigAnonAtom_Body;
00097       fill = bigAnon->mBigAnonAtom_Size;
00098       form = bigAnon->mBigAnonAtom_Form;
00099     }
00100   }
00101   if ( source && fill ) // have an atom with nonempty content?
00102   {
00103     // if we have too many bytes, and yarn seems growable:
00104     if ( fill > outYarn->mYarn_Size && outYarn->mYarn_Grow ) // try grow?
00105       (*outYarn->mYarn_Grow)(outYarn, (mdb_size) fill); // request bigger
00106       
00107     mdb_size size = outYarn->mYarn_Size; // max dest size
00108     if ( fill > size ) // too much atom content?
00109     {
00110       outYarn->mYarn_More = fill - size; // extra atom bytes omitted
00111       fill = size; // copy no more bytes than size of yarn buffer
00112     }
00113     void* dest = outYarn->mYarn_Buf; // where bytes are going
00114     if ( !dest ) // nil destination address buffer?
00115       fill = 0; // we can't write any content at all
00116       
00117     if ( fill ) // anything to copy?
00118       MORK_MEMCPY(dest, source, fill); // copy fill bytes to yarn
00119       
00120     outYarn->mYarn_Fill = fill; // tell yarn size of copied content
00121   }
00122   else // no content to put into the yarn
00123   {
00124     outYarn->mYarn_Fill = 0; // tell yarn that atom has no bytes
00125   }
00126   outYarn->mYarn_Form = form; // always update the form slot
00127   
00128   return ( source != 0 );
00129 }
00130 
00131 mork_bool
00132 morkAtom::AsBuf(morkBuf& outBuf) const
00133 {
00134   const morkAtom* atom = this;
00135   if ( atom )
00136   {
00137     if ( atom->IsWeeBook() )
00138     {
00139       morkWeeBookAtom* weeBook = (morkWeeBookAtom*) atom;
00140       outBuf.mBuf_Body = weeBook->mWeeBookAtom_Body;
00141       outBuf.mBuf_Fill = weeBook->mAtom_Size;
00142     }
00143     else if ( atom->IsBigBook() )
00144     {
00145       morkBigBookAtom* bigBook = (morkBigBookAtom*) atom;
00146       outBuf.mBuf_Body = bigBook->mBigBookAtom_Body;
00147       outBuf.mBuf_Fill = bigBook->mBigBookAtom_Size;
00148     }
00149     else if ( atom->IsWeeAnon() )
00150     {
00151       morkWeeAnonAtom* weeAnon = (morkWeeAnonAtom*) atom;
00152       outBuf.mBuf_Body = weeAnon->mWeeAnonAtom_Body;
00153       outBuf.mBuf_Fill = weeAnon->mAtom_Size;
00154     }
00155     else if ( atom->IsBigAnon() )
00156     {
00157       morkBigAnonAtom* bigAnon = (morkBigAnonAtom*) atom;
00158       outBuf.mBuf_Body = bigAnon->mBigAnonAtom_Body;
00159       outBuf.mBuf_Fill = bigAnon->mBigAnonAtom_Size;
00160     }
00161     else
00162       atom = 0; // show desire to put empty content in yarn
00163   }
00164   
00165   if ( !atom ) // empty content for yarn?
00166   {
00167     outBuf.mBuf_Body = 0;
00168     outBuf.mBuf_Fill = 0;
00169   }
00170   return ( atom != 0 );
00171 }
00172 
00173 mork_bool
00174 morkAtom::AliasYarn(mdbYarn* outYarn) const
00175 {
00176   outYarn->mYarn_More = 0;
00177   outYarn->mYarn_Form = 0;
00178   const morkAtom* atom = this;
00179   
00180   if ( atom )
00181   {
00182     if ( atom->IsWeeBook() )
00183     {
00184       morkWeeBookAtom* weeBook = (morkWeeBookAtom*) atom;
00185       outYarn->mYarn_Buf = weeBook->mWeeBookAtom_Body;
00186       outYarn->mYarn_Fill = weeBook->mAtom_Size;
00187       outYarn->mYarn_Size = weeBook->mAtom_Size;
00188     }
00189     else if ( atom->IsBigBook() )
00190     {
00191       morkBigBookAtom* bigBook = (morkBigBookAtom*) atom;
00192       outYarn->mYarn_Buf = bigBook->mBigBookAtom_Body;
00193       outYarn->mYarn_Fill = bigBook->mBigBookAtom_Size;
00194       outYarn->mYarn_Size = bigBook->mBigBookAtom_Size;
00195       outYarn->mYarn_Form = bigBook->mBigBookAtom_Form;
00196     }
00197     else if ( atom->IsWeeAnon() )
00198     {
00199       morkWeeAnonAtom* weeAnon = (morkWeeAnonAtom*) atom;
00200       outYarn->mYarn_Buf = weeAnon->mWeeAnonAtom_Body;
00201       outYarn->mYarn_Fill = weeAnon->mAtom_Size;
00202       outYarn->mYarn_Size = weeAnon->mAtom_Size;
00203     }
00204     else if ( atom->IsBigAnon() )
00205     {
00206       morkBigAnonAtom* bigAnon = (morkBigAnonAtom*) atom;
00207       outYarn->mYarn_Buf = bigAnon->mBigAnonAtom_Body;
00208       outYarn->mYarn_Fill = bigAnon->mBigAnonAtom_Size;
00209       outYarn->mYarn_Size = bigAnon->mBigAnonAtom_Size;
00210       outYarn->mYarn_Form = bigAnon->mBigAnonAtom_Form;
00211     }
00212     else
00213       atom = 0; // show desire to put empty content in yarn
00214   }
00215   
00216   if ( !atom ) // empty content for yarn?
00217   {
00218     outYarn->mYarn_Buf = 0;
00219     outYarn->mYarn_Fill = 0;
00220     outYarn->mYarn_Size = 0;
00221     // outYarn->mYarn_Grow = 0; // please don't modify the Grow slot
00222   }
00223   return ( atom != 0 );
00224 }
00225 
00226 mork_aid
00227 morkAtom::GetBookAtomAid() const // zero or book atom's ID
00228 {
00229   return ( this->IsBook() )? ((morkBookAtom*) this)->mBookAtom_Id : 0;
00230 }
00231 
00232 mork_scope
00233 morkAtom::GetBookAtomSpaceScope(morkEnv* ev) const // zero or book's space's scope
00234 {
00235   mork_scope outScope = 0;
00236   if ( this->IsBook() )
00237   {
00238     const morkBookAtom* bookAtom = (const morkBookAtom*) this;
00239     morkAtomSpace* space = bookAtom->mBookAtom_Space;
00240     if ( space->IsAtomSpace() )
00241       outScope = space->SpaceScope();
00242     else
00243       space->NonAtomSpaceTypeError(ev);
00244   }
00245   
00246   return outScope;
00247 }
00248 
00249 void
00250 morkAtom::MakeCellUseForever(morkEnv* ev)
00251 {
00252   MORK_USED_1(ev); 
00253   mAtom_CellUses = morkAtom_kForeverCellUses;
00254 }
00255 
00256 mork_u1
00257 morkAtom::AddCellUse(morkEnv* ev)
00258 {
00259   MORK_USED_1(ev); 
00260   if ( mAtom_CellUses < morkAtom_kMaxCellUses ) // not already maxed out?
00261     ++mAtom_CellUses;
00262     
00263   return mAtom_CellUses;
00264 }
00265 
00266 mork_u1
00267 morkAtom::CutCellUse(morkEnv* ev)
00268 {
00269   if ( mAtom_CellUses ) // any outstanding uses to cut?
00270   {
00271     if ( mAtom_CellUses < morkAtom_kMaxCellUses ) // not frozen at max?
00272       --mAtom_CellUses;
00273   }
00274   else
00275     this->CellUsesUnderflowWarning(ev);
00276     
00277   return mAtom_CellUses;
00278 }
00279 
00280 /*static*/ void
00281 morkAtom::CellUsesUnderflowWarning(morkEnv* ev)
00282 {
00283   ev->NewWarning("mAtom_CellUses underflow");
00284 }
00285 
00286 /*static*/ void
00287 morkAtom::BadAtomKindError(morkEnv* ev)
00288 {
00289   ev->NewError("bad mAtom_Kind");
00290 }
00291 
00292 /*static*/ void
00293 morkAtom::ZeroAidError(morkEnv* ev)
00294 {
00295   ev->NewError("zero atom ID");
00296 }
00297 
00298 /*static*/ void
00299 morkAtom::AtomSizeOverflowError(morkEnv* ev)
00300 {
00301   ev->NewError("atom mAtom_Size overflow");
00302 }
00303 
00304 void
00305 morkOidAtom::InitRowOidAtom(morkEnv* ev, const mdbOid& inOid)
00306 {
00307   MORK_USED_1(ev); 
00308   mAtom_CellUses = 0;
00309   mAtom_Kind = morkAtom_kKindRowOid;
00310   mAtom_Change = morkChange_kNil;
00311   mAtom_Size = 0;
00312   mOidAtom_Oid = inOid; // bitwise copy
00313 }
00314 
00315 void
00316 morkOidAtom::InitTableOidAtom(morkEnv* ev, const mdbOid& inOid)
00317 {
00318   MORK_USED_1(ev); 
00319   mAtom_CellUses = 0;
00320   mAtom_Kind = morkAtom_kKindTableOid;
00321   mAtom_Change = morkChange_kNil;
00322   mAtom_Size = 0;
00323   mOidAtom_Oid = inOid; // bitwise copy
00324 }
00325 
00326 void
00327 morkWeeAnonAtom::InitWeeAnonAtom(morkEnv* ev, const morkBuf& inBuf)
00328 {
00329   mAtom_Kind = 0;
00330   mAtom_Change = morkChange_kNil;
00331   if ( inBuf.mBuf_Fill <= morkAtom_kMaxByteSize )
00332   {
00333     mAtom_CellUses = 0;
00334     mAtom_Kind = morkAtom_kKindWeeAnon;
00335     mork_size size = inBuf.mBuf_Fill;
00336     mAtom_Size = (mork_u1) size;
00337     if ( size && inBuf.mBuf_Body )
00338       MORK_MEMCPY(mWeeAnonAtom_Body, inBuf.mBuf_Body, size);
00339         
00340     mWeeAnonAtom_Body[ size ] = 0;
00341   }
00342   else
00343     this->AtomSizeOverflowError(ev);
00344 }
00345 
00346 void
00347 morkBigAnonAtom::InitBigAnonAtom(morkEnv* ev, const morkBuf& inBuf,
00348   mork_cscode inForm)
00349 {
00350   MORK_USED_1(ev); 
00351   mAtom_CellUses = 0;
00352   mAtom_Kind = morkAtom_kKindBigAnon;
00353   mAtom_Change = morkChange_kNil;
00354   mAtom_Size = 0;
00355   mBigAnonAtom_Form = inForm;
00356   mork_size size = inBuf.mBuf_Fill;
00357   mBigAnonAtom_Size = size;
00358   if ( size && inBuf.mBuf_Body )
00359     MORK_MEMCPY(mBigAnonAtom_Body, inBuf.mBuf_Body, size);
00360         
00361   mBigAnonAtom_Body[ size ] = 0;
00362 }
00363 
00364 /*static*/ void
00365 morkBookAtom::NonBookAtomTypeError(morkEnv* ev)
00366 {
00367   ev->NewError("non morkBookAtom");
00368 }
00369 
00370 mork_u4
00371 morkBookAtom::HashFormAndBody(morkEnv* ev) const
00372 {
00373   // This hash is obviously a variation of the dragon book string hash.
00374   // (I won't bother to explain or rationalize this usage for you.)
00375   
00376   register mork_u4 outHash = 0; // hash value returned
00377   register unsigned char c; // next character
00378   register const mork_u1* body; // body of bytes to hash
00379   mork_size size = 0; // the number of bytes to hash
00380 
00381   if ( this->IsWeeBook() )
00382   {
00383     size = mAtom_Size;
00384     body = ((const morkWeeBookAtom*) this)->mWeeBookAtom_Body;
00385   }
00386   else if ( this->IsBigBook() )
00387   {
00388     size = ((const morkBigBookAtom*) this)->mBigBookAtom_Size;
00389     body = ((const morkBigBookAtom*) this)->mBigBookAtom_Body;
00390   }
00391   else if ( this->IsFarBook() )
00392   {
00393     size = ((const morkFarBookAtom*) this)->mFarBookAtom_Size;
00394     body = ((const morkFarBookAtom*) this)->mFarBookAtom_Body;
00395   }
00396   else
00397   {
00398     this->NonBookAtomTypeError(ev);
00399     return 0;
00400   }
00401   
00402   const mork_u1* end = body + size;
00403   while ( body < end )
00404   {
00405     c = *body++;
00406     outHash <<= 4;
00407     outHash += c;
00408     mork_u4 top = outHash & 0xF0000000L; // top four bits
00409     if ( top ) // any of high four bits equal to one? 
00410     {
00411       outHash ^= (top >> 24); // fold down high bits
00412       outHash ^= top; // zero top four bits
00413     }
00414   }
00415     
00416   return outHash;
00417 }
00418 
00419 mork_bool
00420 morkBookAtom::EqualFormAndBody(morkEnv* ev, const morkBookAtom* inAtom) const
00421 {
00422   mork_bool outEqual = morkBool_kFalse;
00423   
00424   const mork_u1* body = 0; // body of inAtom bytes to compare
00425   mork_size size; // the number of inAtom bytes to compare
00426   mork_cscode form; // nominal charset for ioAtom
00427 
00428   if ( inAtom->IsWeeBook() )
00429   {
00430     size = inAtom->mAtom_Size;
00431     body = ((const morkWeeBookAtom*) inAtom)->mWeeBookAtom_Body;
00432     form = 0;
00433   }
00434   else if ( inAtom->IsBigBook() )
00435   {
00436     size = ((const morkBigBookAtom*) inAtom)->mBigBookAtom_Size;
00437     body = ((const morkBigBookAtom*) inAtom)->mBigBookAtom_Body;
00438     form = ((const morkBigBookAtom*) inAtom)->mBigBookAtom_Form;
00439   }
00440   else if ( inAtom->IsFarBook() )
00441   {
00442     size = ((const morkFarBookAtom*) inAtom)->mFarBookAtom_Size;
00443     body = ((const morkFarBookAtom*) inAtom)->mFarBookAtom_Body;
00444     form = ((const morkFarBookAtom*) inAtom)->mFarBookAtom_Form;
00445   }
00446   else
00447   {
00448     inAtom->NonBookAtomTypeError(ev);
00449     return morkBool_kFalse;
00450   }
00451 
00452   const mork_u1* thisBody = 0; // body of bytes in this to compare
00453   mork_size thisSize; // the number of bytes in this to compare
00454   mork_cscode thisForm; // nominal charset for this atom
00455   
00456   if ( this->IsWeeBook() )
00457   {
00458     thisSize = mAtom_Size;
00459     thisBody = ((const morkWeeBookAtom*) this)->mWeeBookAtom_Body;
00460     thisForm = 0;
00461   }
00462   else if ( this->IsBigBook() )
00463   {
00464     thisSize = ((const morkBigBookAtom*) this)->mBigBookAtom_Size;
00465     thisBody = ((const morkBigBookAtom*) this)->mBigBookAtom_Body;
00466     thisForm = ((const morkBigBookAtom*) this)->mBigBookAtom_Form;
00467   }
00468   else if ( this->IsFarBook() )
00469   {
00470     thisSize = ((const morkFarBookAtom*) this)->mFarBookAtom_Size;
00471     thisBody = ((const morkFarBookAtom*) this)->mFarBookAtom_Body;
00472     thisForm = ((const morkFarBookAtom*) this)->mFarBookAtom_Form;
00473   }
00474   else
00475   {
00476     this->NonBookAtomTypeError(ev);
00477     return morkBool_kFalse;
00478   }
00479   
00480   // if atoms are empty, form is irrelevant
00481   if ( body && thisBody && size == thisSize && (!size || form == thisForm ))
00482     outEqual = (MORK_MEMCMP(body, thisBody, size) == 0);
00483   
00484   return outEqual;
00485 }
00486 
00487 
00488 void
00489 morkBookAtom::CutBookAtomFromSpace(morkEnv* ev)
00490 {
00491   morkAtomSpace* space = mBookAtom_Space;
00492   if ( space )
00493   {
00494     mBookAtom_Space = 0;
00495     space->mAtomSpace_AtomBodies.CutAtom(ev, this);
00496     space->mAtomSpace_AtomAids.CutAtom(ev, this);
00497   }
00498   else
00499     ev->NilPointerError();
00500 }
00501 
00502 morkWeeBookAtom::morkWeeBookAtom(mork_aid inAid)
00503 {
00504   mAtom_Kind = morkAtom_kKindWeeBook;
00505   mAtom_CellUses = 0;
00506   mAtom_Change = morkChange_kNil;
00507   mAtom_Size = 0;
00508 
00509   mBookAtom_Space = 0;
00510   mBookAtom_Id = inAid;
00511 
00512   mWeeBookAtom_Body[ 0 ] = 0;
00513 }
00514 
00515 void
00516 morkWeeBookAtom::InitWeeBookAtom(morkEnv* ev, const morkBuf& inBuf,
00517   morkAtomSpace* ioSpace, mork_aid inAid)
00518 {
00519   mAtom_Kind = 0;
00520   mAtom_Change = morkChange_kNil;
00521   if ( ioSpace )
00522   {
00523     if ( inAid )
00524     {
00525       if ( inBuf.mBuf_Fill <= morkAtom_kMaxByteSize )
00526       {
00527         mAtom_CellUses = 0;
00528         mAtom_Kind = morkAtom_kKindWeeBook;
00529         mBookAtom_Space = ioSpace;
00530         mBookAtom_Id = inAid;
00531         mork_size size = inBuf.mBuf_Fill;
00532         mAtom_Size = (mork_u1) size;
00533         if ( size && inBuf.mBuf_Body )
00534           MORK_MEMCPY(mWeeBookAtom_Body, inBuf.mBuf_Body, size);
00535         
00536         mWeeBookAtom_Body[ size ] = 0;
00537       }
00538       else
00539         this->AtomSizeOverflowError(ev);
00540     }
00541     else
00542       this->ZeroAidError(ev);
00543   }
00544   else
00545     ev->NilPointerError();
00546 }
00547 
00548 void
00549 morkBigBookAtom::InitBigBookAtom(morkEnv* ev, const morkBuf& inBuf,
00550   mork_cscode inForm, morkAtomSpace* ioSpace, mork_aid inAid)
00551 {
00552   mAtom_Kind = 0;
00553   mAtom_Change = morkChange_kNil;
00554   if ( ioSpace )
00555   {
00556     if ( inAid )
00557     {
00558       mAtom_CellUses = 0;
00559       mAtom_Kind = morkAtom_kKindBigBook;
00560       mAtom_Size = 0;
00561       mBookAtom_Space = ioSpace;
00562       mBookAtom_Id = inAid;
00563       mBigBookAtom_Form = inForm;
00564       mork_size size = inBuf.mBuf_Fill;
00565       mBigBookAtom_Size = size;
00566       if ( size && inBuf.mBuf_Body )
00567         MORK_MEMCPY(mBigBookAtom_Body, inBuf.mBuf_Body, size);
00568         
00569       mBigBookAtom_Body[ size ] = 0;
00570     }
00571     else
00572       this->ZeroAidError(ev);
00573   }
00574   else
00575     ev->NilPointerError();
00576 }
00577 
00578 void morkFarBookAtom::InitFarBookAtom(morkEnv* ev, const morkBuf& inBuf,
00579   mork_cscode inForm, morkAtomSpace* ioSpace, mork_aid inAid)
00580 {
00581   mAtom_Kind = 0;
00582   mAtom_Change = morkChange_kNil;
00583   if ( ioSpace )
00584   {
00585     if ( inAid )
00586     {
00587       mAtom_CellUses = 0;
00588       mAtom_Kind = morkAtom_kKindFarBook;
00589       mAtom_Size = 0;
00590       mBookAtom_Space = ioSpace;
00591       mBookAtom_Id = inAid;
00592       mFarBookAtom_Form = inForm;
00593       mFarBookAtom_Size = inBuf.mBuf_Fill;
00594       mFarBookAtom_Body = (mork_u1*) inBuf.mBuf_Body;
00595     }
00596     else
00597       this->ZeroAidError(ev);
00598   }
00599   else
00600     ev->NilPointerError();
00601 }
00602 
00603 //3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
00604