mirror of https://github.com/roytam1/UXP
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
297 lines
6.9 KiB
297 lines
6.9 KiB
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
|
/* This Source Code Form is subject to the terms of the Mozilla Public |
|
* License, v. 2.0. If a copy of the MPL was not distributed with this |
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
|
|
#include "nscore.h" |
|
|
|
#ifndef _MDB_ |
|
#include "mdb.h" |
|
#endif |
|
|
|
#ifndef _MORK_ |
|
#include "mork.h" |
|
#endif |
|
|
|
#ifndef _MORKNODE_ |
|
#include "morkNode.h" |
|
#endif |
|
|
|
#ifndef _MORKENV_ |
|
#include "morkEnv.h" |
|
#endif |
|
|
|
#ifndef _MORKARRAY_ |
|
#include "morkArray.h" |
|
#endif |
|
|
|
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789 |
|
|
|
// ````` ````` ````` ````` ````` |
|
// { ===== begin morkNode interface ===== |
|
|
|
/*public virtual*/ void |
|
morkArray::CloseMorkNode(morkEnv* ev) // CloseTable() only if open |
|
{ |
|
if ( this->IsOpenNode() ) |
|
{ |
|
this->MarkClosing(); |
|
this->CloseArray(ev); |
|
this->MarkShut(); |
|
} |
|
} |
|
|
|
/*public virtual*/ |
|
morkArray::~morkArray() // assert CloseTable() executed earlier |
|
{ |
|
MORK_ASSERT(this->IsShutNode()); |
|
MORK_ASSERT(mArray_Slots==0); |
|
} |
|
|
|
/*public non-poly*/ |
|
morkArray::morkArray(morkEnv* ev, const morkUsage& inUsage, |
|
nsIMdbHeap* ioHeap, mork_size inSize, nsIMdbHeap* ioSlotHeap) |
|
: morkNode(ev, inUsage, ioHeap) |
|
, mArray_Slots( 0 ) |
|
, mArray_Heap( 0 ) |
|
, mArray_Fill( 0 ) |
|
, mArray_Size( 0 ) |
|
, mArray_Seed( (mork_u4)NS_PTR_TO_INT32(this) ) // "random" integer assignment |
|
{ |
|
if ( ev->Good() ) |
|
{ |
|
if ( ioSlotHeap ) |
|
{ |
|
nsIMdbHeap_SlotStrongHeap(ioSlotHeap, ev, &mArray_Heap); |
|
if ( ev->Good() ) |
|
{ |
|
if ( inSize < 3 ) |
|
inSize = 3; |
|
mdb_size byteSize = inSize * sizeof(void*); |
|
void** block = 0; |
|
ioSlotHeap->Alloc(ev->AsMdbEnv(), byteSize, (void**) &block); |
|
if ( block && ev->Good() ) |
|
{ |
|
mArray_Slots = block; |
|
mArray_Size = inSize; |
|
MORK_MEMSET(mArray_Slots, 0, byteSize); |
|
if ( ev->Good() ) |
|
mNode_Derived = morkDerived_kArray; |
|
} |
|
} |
|
} |
|
else |
|
ev->NilPointerError(); |
|
} |
|
} |
|
|
|
/*public non-poly*/ void |
|
morkArray::CloseArray(morkEnv* ev) // called by CloseMorkNode(); |
|
{ |
|
if ( this->IsNode() ) |
|
{ |
|
if ( mArray_Heap && mArray_Slots ) |
|
mArray_Heap->Free(ev->AsMdbEnv(), mArray_Slots); |
|
|
|
mArray_Slots = 0; |
|
mArray_Size = 0; |
|
mArray_Fill = 0; |
|
++mArray_Seed; |
|
nsIMdbHeap_SlotStrongHeap((nsIMdbHeap*) 0, ev, &mArray_Heap); |
|
this->MarkShut(); |
|
} |
|
else |
|
this->NonNodeError(ev); |
|
} |
|
|
|
// } ===== end morkNode methods ===== |
|
// ````` ````` ````` ````` ````` |
|
|
|
/*static*/ void |
|
morkArray::NonArrayTypeError(morkEnv* ev) |
|
{ |
|
ev->NewError("non morkArray"); |
|
} |
|
|
|
/*static*/ void |
|
morkArray::IndexBeyondEndError(morkEnv* ev) |
|
{ |
|
ev->NewError("array index beyond end"); |
|
} |
|
|
|
/*static*/ void |
|
morkArray::NilSlotsAddressError(morkEnv* ev) |
|
{ |
|
ev->NewError("nil mArray_Slots"); |
|
} |
|
|
|
/*static*/ void |
|
morkArray::FillBeyondSizeError(morkEnv* ev) |
|
{ |
|
ev->NewError("mArray_Fill > mArray_Size"); |
|
} |
|
|
|
mork_bool |
|
morkArray::Grow(morkEnv* ev, mork_size inNewSize) |
|
// Grow() returns true if capacity becomes >= inNewSize and ev->Good() |
|
{ |
|
if ( ev->Good() && inNewSize > mArray_Size ) // make array larger? |
|
{ |
|
if ( mArray_Fill <= mArray_Size ) // fill and size fit the invariant? |
|
{ |
|
if (mArray_Size <= 3) |
|
inNewSize = mArray_Size + 3; |
|
else |
|
inNewSize = mArray_Size * 2;// + 3; // try doubling size here - used to grow by 3 |
|
|
|
mdb_size newByteSize = inNewSize * sizeof(void*); |
|
void** newBlock = 0; |
|
mArray_Heap->Alloc(ev->AsMdbEnv(), newByteSize, (void**) &newBlock); |
|
if ( newBlock && ev->Good() ) // okay new block? |
|
{ |
|
void** oldSlots = mArray_Slots; |
|
void** oldEnd = oldSlots + mArray_Fill; |
|
|
|
void** newSlots = newBlock; |
|
void** newEnd = newBlock + inNewSize; |
|
|
|
while ( oldSlots < oldEnd ) |
|
*newSlots++ = *oldSlots++; |
|
|
|
while ( newSlots < newEnd ) |
|
*newSlots++ = (void*) 0; |
|
|
|
oldSlots = mArray_Slots; |
|
mArray_Size = inNewSize; |
|
mArray_Slots = newBlock; |
|
mArray_Heap->Free(ev->AsMdbEnv(), oldSlots); |
|
} |
|
} |
|
else |
|
this->FillBeyondSizeError(ev); |
|
} |
|
++mArray_Seed; // always modify seed, since caller intends to add slots |
|
return ( ev->Good() && mArray_Size >= inNewSize ); |
|
} |
|
|
|
void* |
|
morkArray::SafeAt(morkEnv* ev, mork_pos inPos) |
|
{ |
|
if ( mArray_Slots ) |
|
{ |
|
if ( inPos >= 0 && inPos < (mork_pos) mArray_Fill ) |
|
return mArray_Slots[ inPos ]; |
|
else |
|
this->IndexBeyondEndError(ev); |
|
} |
|
else |
|
this->NilSlotsAddressError(ev); |
|
|
|
return (void*) 0; |
|
} |
|
|
|
void |
|
morkArray::SafeAtPut(morkEnv* ev, mork_pos inPos, void* ioSlot) |
|
{ |
|
if ( mArray_Slots ) |
|
{ |
|
if ( inPos >= 0 && inPos < (mork_pos) mArray_Fill ) |
|
{ |
|
mArray_Slots[ inPos ] = ioSlot; |
|
++mArray_Seed; |
|
} |
|
else |
|
this->IndexBeyondEndError(ev); |
|
} |
|
else |
|
this->NilSlotsAddressError(ev); |
|
} |
|
|
|
mork_pos |
|
morkArray::AppendSlot(morkEnv* ev, void* ioSlot) |
|
{ |
|
mork_pos outPos = -1; |
|
if ( mArray_Slots ) |
|
{ |
|
mork_fill fill = mArray_Fill; |
|
if ( this->Grow(ev, fill+1) ) |
|
{ |
|
outPos = (mork_pos) fill; |
|
mArray_Slots[ fill ] = ioSlot; |
|
mArray_Fill = fill + 1; |
|
// note Grow() increments mArray_Seed |
|
} |
|
} |
|
else |
|
this->NilSlotsAddressError(ev); |
|
|
|
return outPos; |
|
} |
|
|
|
void |
|
morkArray::AddSlot(morkEnv* ev, mork_pos inPos, void* ioSlot) |
|
{ |
|
if ( mArray_Slots ) |
|
{ |
|
mork_fill fill = mArray_Fill; |
|
if ( this->Grow(ev, fill+1) ) |
|
{ |
|
void** slot = mArray_Slots; // the slot vector |
|
void** end = slot + fill; // one past the last used array slot |
|
slot += inPos; // the slot to be added |
|
|
|
while ( --end >= slot ) // another slot to move upward? |
|
end[ 1 ] = *end; |
|
|
|
*slot = ioSlot; |
|
mArray_Fill = fill + 1; |
|
// note Grow() increments mArray_Seed |
|
} |
|
} |
|
else |
|
this->NilSlotsAddressError(ev); |
|
} |
|
|
|
void |
|
morkArray::CutSlot(morkEnv* ev, mork_pos inPos) |
|
{ |
|
MORK_USED_1(ev); |
|
mork_fill fill = mArray_Fill; |
|
if ( inPos >= 0 && inPos < (mork_pos) fill ) // cutting slot in used array portion? |
|
{ |
|
void** slot = mArray_Slots; // the slot vector |
|
void** end = slot + fill; // one past the last used array slot |
|
slot += inPos; // the slot to be cut |
|
|
|
while ( ++slot < end ) // another slot to move downward? |
|
slot[ -1 ] = *slot; |
|
|
|
slot[ -1 ] = 0; // clear the last used slot which is now unused |
|
|
|
// note inPos<fill implies fill>0, so fill-1 must be nonnegative: |
|
mArray_Fill = fill - 1; |
|
++mArray_Seed; |
|
} |
|
} |
|
|
|
void |
|
morkArray::CutAllSlots(morkEnv* ev) |
|
{ |
|
if ( mArray_Slots ) |
|
{ |
|
if ( mArray_Fill <= mArray_Size ) |
|
{ |
|
mdb_size oldByteSize = mArray_Fill * sizeof(void*); |
|
MORK_MEMSET(mArray_Slots, 0, oldByteSize); |
|
} |
|
else |
|
this->FillBeyondSizeError(ev); |
|
} |
|
else |
|
this->NilSlotsAddressError(ev); |
|
|
|
++mArray_Seed; |
|
mArray_Fill = 0; |
|
} |
|
|
|
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
|
|
|