Back to index

lightning-sunbird  0.9+nobinonly
morkArray.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 #include "nscore.h"
00039 
00040 #ifndef _MDB_
00041 #include "mdb.h"
00042 #endif
00043 
00044 #ifndef _MORK_
00045 #include "mork.h"
00046 #endif
00047 
00048 #ifndef _MORKNODE_
00049 #include "morkNode.h"
00050 #endif
00051 
00052 #ifndef _MORKENV_
00053 #include "morkEnv.h"
00054 #endif
00055 
00056 #ifndef _MORKARRAY_
00057 #include "morkArray.h"
00058 #endif
00059 
00060 //3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
00061 
00062 // ````` ````` ````` ````` ````` 
00063 // { ===== begin morkNode interface =====
00064 
00065 /*public virtual*/ void
00066 morkArray::CloseMorkNode(morkEnv* ev) // CloseTable() only if open
00067 {
00068   if ( this->IsOpenNode() )
00069   {
00070     this->MarkClosing();
00071     this->CloseArray(ev);
00072     this->MarkShut();
00073   }
00074 }
00075 
00076 /*public virtual*/
00077 morkArray::~morkArray() // assert CloseTable() executed earlier
00078 {
00079   MORK_ASSERT(this->IsShutNode());
00080   MORK_ASSERT(mArray_Slots==0);
00081 }
00082 
00083 /*public non-poly*/
00084 morkArray::morkArray(morkEnv* ev, const morkUsage& inUsage,
00085     nsIMdbHeap* ioHeap, mork_size inSize, nsIMdbHeap* ioSlotHeap)
00086 : morkNode(ev, inUsage, ioHeap)
00087 , mArray_Slots( 0 )
00088 , mArray_Heap( 0 )
00089 , mArray_Fill( 0 )
00090 , mArray_Size( 0 )
00091 , mArray_Seed( (mork_u4)NS_PTR_TO_INT32(this) ) // "random" integer assignment
00092 {
00093   if ( ev->Good() )
00094   {
00095     if ( ioSlotHeap )
00096     {
00097       nsIMdbHeap_SlotStrongHeap(ioSlotHeap, ev, &mArray_Heap);
00098       if ( ev->Good() )
00099       {
00100         if ( inSize < 3 )
00101           inSize = 3;
00102         mdb_size byteSize = inSize * sizeof(void*);
00103         void** block = 0;
00104         ioSlotHeap->Alloc(ev->AsMdbEnv(), byteSize, (void**) &block);
00105         if ( block && ev->Good() )
00106         {
00107           mArray_Slots = block;
00108           mArray_Size = inSize;
00109           MORK_MEMSET(mArray_Slots, 0, byteSize);
00110           if ( ev->Good() )
00111             mNode_Derived = morkDerived_kArray;
00112         }
00113       }
00114     }
00115     else
00116       ev->NilPointerError();
00117   }
00118 }
00119 
00120 /*public non-poly*/ void
00121 morkArray::CloseArray(morkEnv* ev) // called by CloseMorkNode();
00122 {
00123   if ( this )
00124   {
00125     if ( this->IsNode() )
00126     {
00127       if ( mArray_Heap && mArray_Slots )
00128         mArray_Heap->Free(ev->AsMdbEnv(), mArray_Slots);
00129         
00130       mArray_Slots = 0;
00131       mArray_Size = 0;
00132       mArray_Fill = 0;
00133       ++mArray_Seed;
00134       nsIMdbHeap_SlotStrongHeap((nsIMdbHeap*) 0, ev, &mArray_Heap);
00135       this->MarkShut();
00136     }
00137     else
00138       this->NonNodeError(ev);
00139   }
00140   else
00141     ev->NilPointerError();
00142 }
00143 
00144 // } ===== end morkNode methods =====
00145 // ````` ````` ````` ````` ````` 
00146 
00147 /*static*/ void
00148 morkArray::NonArrayTypeError(morkEnv* ev)
00149 {
00150   ev->NewError("non morkArray");
00151 }
00152 
00153 /*static*/ void
00154 morkArray::IndexBeyondEndError(morkEnv* ev)
00155 {
00156   ev->NewError("array index beyond end");
00157 }
00158 
00159 /*static*/ void
00160 morkArray::NilSlotsAddressError(morkEnv* ev)
00161 {
00162   ev->NewError("nil mArray_Slots");
00163 }
00164 
00165 /*static*/ void
00166 morkArray::FillBeyondSizeError(morkEnv* ev)
00167 {
00168   ev->NewError("mArray_Fill > mArray_Size");
00169 }
00170 
00171 mork_bool
00172 morkArray::Grow(morkEnv* ev, mork_size inNewSize)
00173 // Grow() returns true if capacity becomes >= inNewSize and ev->Good()
00174 {
00175   if ( ev->Good() && inNewSize > mArray_Size ) // make array larger?
00176   {
00177     if ( mArray_Fill <= mArray_Size ) // fill and size fit the invariant?
00178     {
00179       if (mArray_Size <= 3)
00180         inNewSize = mArray_Size + 3;
00181       else
00182         inNewSize = mArray_Size  * 2;// + 3;  // try doubling size here - used to grow by 3
00183         
00184       mdb_size newByteSize = inNewSize * sizeof(void*);
00185       void** newBlock = 0;
00186       mArray_Heap->Alloc(ev->AsMdbEnv(), newByteSize, (void**) &newBlock);
00187       if ( newBlock && ev->Good() ) // okay new block?
00188       {
00189         void** oldSlots = mArray_Slots;
00190         void** oldEnd = oldSlots + mArray_Fill;
00191         
00192         void** newSlots = newBlock;
00193         void** newEnd = newBlock + inNewSize;
00194         
00195         while ( oldSlots < oldEnd )
00196           *newSlots++ = *oldSlots++;
00197           
00198         while ( newSlots < newEnd )
00199           *newSlots++ = (void*) 0;
00200 
00201         oldSlots = mArray_Slots;
00202         mArray_Size = inNewSize;
00203         mArray_Slots = newBlock;
00204         mArray_Heap->Free(ev->AsMdbEnv(), oldSlots);
00205       }
00206     }
00207     else
00208       this->FillBeyondSizeError(ev);
00209   }
00210   ++mArray_Seed; // always modify seed, since caller intends to add slots
00211   return ( ev->Good() && mArray_Size >= inNewSize );
00212 }
00213 
00214 void*
00215 morkArray::SafeAt(morkEnv* ev, mork_pos inPos)
00216 {
00217   if ( mArray_Slots )
00218   {
00219     if ( inPos >= 0 && inPos < (mork_pos) mArray_Fill )
00220       return mArray_Slots[ inPos ];
00221     else
00222       this->IndexBeyondEndError(ev);
00223   }
00224   else
00225     this->NilSlotsAddressError(ev);
00226     
00227   return (void*) 0;
00228 }
00229 
00230 void
00231 morkArray::SafeAtPut(morkEnv* ev, mork_pos inPos, void* ioSlot)
00232 {
00233   if ( mArray_Slots )
00234   {
00235     if ( inPos >= 0 && inPos < (mork_pos) mArray_Fill )
00236     {
00237       mArray_Slots[ inPos ] = ioSlot;
00238       ++mArray_Seed;
00239     }
00240     else
00241       this->IndexBeyondEndError(ev);
00242   }
00243   else
00244     this->NilSlotsAddressError(ev);
00245 }
00246 
00247 mork_pos
00248 morkArray::AppendSlot(morkEnv* ev, void* ioSlot)
00249 {
00250   mork_pos outPos = -1;
00251   if ( mArray_Slots )
00252   {
00253     mork_fill fill = mArray_Fill;
00254     if ( this->Grow(ev, fill+1) )
00255     {
00256       outPos = (mork_pos) fill;
00257       mArray_Slots[ fill ] = ioSlot;
00258       mArray_Fill = fill + 1;
00259       // note Grow() increments mArray_Seed
00260     }
00261   }
00262   else
00263     this->NilSlotsAddressError(ev);
00264     
00265   return outPos;
00266 }
00267 
00268 void
00269 morkArray::AddSlot(morkEnv* ev, mork_pos inPos, void* ioSlot)
00270 {
00271   if ( mArray_Slots )
00272   {
00273     mork_fill fill = mArray_Fill;
00274     if ( this->Grow(ev, fill+1) )
00275     {
00276       void** slot = mArray_Slots; // the slot vector
00277       void** end = slot + fill; // one past the last used array slot
00278       slot += inPos; // the slot to be added
00279 
00280       while ( --end >= slot ) // another slot to move upward?
00281         end[ 1 ] = *end;
00282 
00283       *slot = ioSlot;
00284       mArray_Fill = fill + 1;
00285       // note Grow() increments mArray_Seed
00286     }
00287   }
00288   else
00289     this->NilSlotsAddressError(ev);
00290 }
00291 
00292 void
00293 morkArray::CutSlot(morkEnv* ev, mork_pos inPos)
00294 {
00295   MORK_USED_1(ev);
00296   mork_fill fill = mArray_Fill;
00297   if ( inPos >= 0 && inPos < (mork_pos) fill ) // cutting slot in used array portion?
00298   {
00299     void** slot = mArray_Slots; // the slot vector
00300     void** end = slot + fill; // one past the last used array slot
00301     slot += inPos; // the slot to be cut
00302     
00303     while ( ++slot < end ) // another slot to move downward?
00304       slot[ -1 ] = *slot;
00305       
00306     slot[ -1 ] = 0; // clear the last used slot which is now unused
00307     
00308     // note inPos<fill implies fill>0, so fill-1 must be nonnegative:
00309     mArray_Fill = fill - 1;
00310     ++mArray_Seed;
00311   }
00312 }
00313 
00314 void
00315 morkArray::CutAllSlots(morkEnv* ev)
00316 {
00317   if ( mArray_Slots )
00318   {
00319     if ( mArray_Fill <= mArray_Size )
00320     {
00321       mdb_size oldByteSize = mArray_Fill * sizeof(void*);
00322       MORK_MEMSET(mArray_Slots, 0, oldByteSize);
00323     }
00324     else
00325       this->FillBeyondSizeError(ev);
00326   }
00327   else
00328     this->NilSlotsAddressError(ev);
00329 
00330   ++mArray_Seed;
00331   mArray_Fill = 0;
00332 }
00333 
00334 //3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789