ChunkedIntArraypublic final class ChunkedIntArray extends Object ChunkedIntArray is an extensible array of blocks of integers.
(I'd consider Vector, but it's unable to handle integers except by
turning them into Objects.)
Making this a separate class means some call-and-return overhead. But
doing it all inline tends to be fragile and expensive in coder time,
not to mention driving up code size. If you want to inline it, feel free.
The Java text suggest that private and Final methods may be inlined,
and one can argue that this beast need not be made subclassable...
%REVIEW% This has strong conceptual overlap with the IntVector class.
It would probably be a good thing to merge the two, when time permits. |
Fields Summary |
---|
final int | slotsize | static final int | lowbits | static final int | chunkalloc | static final int | lowmask | ChunksVector | chunks | final int[] | fastArray | int | lastUsed |
Constructors Summary |
---|
ChunkedIntArray(int slotsize)Create a new CIA with specified record size. Currently record size MUST
be a power of two... and in fact is hardcoded to 4.
if(this.slotsize<slotsize)
throw new ArrayIndexOutOfBoundsException(XMLMessages.createXMLMessage(XMLErrorResources.ER_CHUNKEDINTARRAY_NOT_SUPPORTED, new Object[]{Integer.toString(slotsize)})); //"ChunkedIntArray("+slotsize+") not currently supported");
else if (this.slotsize>slotsize)
System.out.println("*****WARNING: ChunkedIntArray("+slotsize+") wasting "+(this.slotsize-slotsize)+" words per slot");
chunks.addElement(fastArray);
|
Methods Summary |
---|
int | appendSlot(int w0, int w1, int w2, int w3)Append a 4-integer record to the CIA, starting with record 1. (Since
arrays are initialized to all-0, 0 has been reserved as the "unknown"
value in DTM.)
/*
try
{
int newoffset = (lastUsed+1)*slotsize;
fastArray[newoffset] = w0;
fastArray[newoffset+1] = w1;
fastArray[newoffset+2] = w2;
fastArray[newoffset+3] = w3;
return ++lastUsed;
}
catch(ArrayIndexOutOfBoundsException aioobe)
*/
{
final int slotsize=4;
int newoffset = (lastUsed+1)*slotsize;
int chunkpos = newoffset >> lowbits;
int slotpos = (newoffset & lowmask);
// Grow if needed
if (chunkpos > chunks.size() - 1)
chunks.addElement(new int[chunkalloc]);
int[] chunk = chunks.elementAt(chunkpos);
chunk[slotpos] = w0;
chunk[slotpos+1] = w1;
chunk[slotpos+2] = w2;
chunk[slotpos+3] = w3;
return ++lastUsed;
}
| void | discardLast()Disard the highest-numbered record. This is used in the string-buffer
CIA; when only a single characters() chunk has been recieved, its index
is moved into the Text node rather than being referenced by indirection
into the text accumulator.
--lastUsed;
| int | readEntry(int position, int offset)Retrieve an integer from the CIA by record number and column within
the record, both 0-based (though position 0 is reserved for special
purposes).
/*
try
{
return fastArray[(position*slotsize)+offset];
}
catch(ArrayIndexOutOfBoundsException aioobe)
*/
{
// System.out.println("Using slow read (1)");
if (offset>=slotsize)
throw new ArrayIndexOutOfBoundsException(XMLMessages.createXMLMessage(XMLErrorResources.ER_OFFSET_BIGGER_THAN_SLOT, null)); //"Offset bigger than slot");
position*=slotsize;
int chunkpos = position >> lowbits;
int slotpos = position & lowmask;
int[] chunk = chunks.elementAt(chunkpos);
return chunk[slotpos + offset];
}
| void | readSlot(int position, int[] buffer)Retrieve the contents of a record into a user-supplied buffer array.
Used to reduce addressing overhead when code will access several
columns of the record.
/*
try
{
System.arraycopy(fastArray, position*slotsize, buffer, 0, slotsize);
}
catch(ArrayIndexOutOfBoundsException aioobe)
*/
{
// System.out.println("Using slow read (2): "+position);
position *= slotsize;
int chunkpos = position >> lowbits;
int slotpos = (position & lowmask);
// Grow if needed
if (chunkpos > chunks.size() - 1)
chunks.addElement(new int[chunkalloc]);
int[] chunk = chunks.elementAt(chunkpos);
System.arraycopy(chunk,slotpos,buffer,0,slotsize);
}
| int | slotsUsed()
return lastUsed;
| int | specialFind(int startPos, int position)
// We have to look all the way up the ancestor chain
// to make sure we don't have an ancestor.
int ancestor = startPos;
while(ancestor > 0)
{
// Get the node whose index == ancestor
ancestor*=slotsize;
int chunkpos = ancestor >> lowbits;
int slotpos = ancestor & lowmask;
int[] chunk = chunks.elementAt(chunkpos);
// Get that node's parent (Note that this assumes w[1]
// is the parent node index. That's really a DTM feature
// rather than a ChunkedIntArray feature.)
ancestor = chunk[slotpos + 1];
if(ancestor == position)
break;
}
if (ancestor <= 0)
{
return position;
}
return -1;
| void | writeEntry(int position, int offset, int value)Overwrite the integer found at a specific record and column.
Used to back-patch existing records, most often changing their
"next sibling" reference from 0 (unknown) to something meaningful
/*
try
{
fastArray[( position*slotsize)+offset] = value;
}
catch(ArrayIndexOutOfBoundsException aioobe)
*/
{
if (offset >= slotsize)
throw new ArrayIndexOutOfBoundsException(XMLMessages.createXMLMessage(XMLErrorResources.ER_OFFSET_BIGGER_THAN_SLOT, null)); //"Offset bigger than slot");
position*=slotsize;
int chunkpos = position >> lowbits;
int slotpos = position & lowmask;
int[] chunk = chunks.elementAt(chunkpos);
chunk[slotpos + offset] = value; // ATOMIC!
}
| void | writeSlot(int position, int w0, int w1, int w2, int w3)Overwrite an entire (4-integer) record at the specified index.
Mostly used to create record 0, the Document node.
position *= slotsize;
int chunkpos = position >> lowbits;
int slotpos = (position & lowmask);
// Grow if needed
if (chunkpos > chunks.size() - 1)
chunks.addElement(new int[chunkalloc]);
int[] chunk = chunks.elementAt(chunkpos);
chunk[slotpos] = w0;
chunk[slotpos + 1] = w1;
chunk[slotpos + 2] = w2;
chunk[slotpos + 3] = w3;
|
|