FileDocCategorySizeDatePackage
ChunkedIntArray.javaAPI DocJava SE 6 API9901Tue Jun 10 00:22:56 BST 2008com.sun.org.apache.xml.internal.dtm.ref

ChunkedIntArray

public 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
intappendSlot(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.)

return
the index at which this record was inserted.

    /*
    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;
    }
  
voiddiscardLast()
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;
  
intreadEntry(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).

param
position int Record number
param
slotpos int Column number

    /*
    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];
    }
  
voidreadSlot(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.

param
position int Record number
param
buffer int[] Integer array provided by user, must be large enough to hold a complete 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);
    }
  
intslotsUsed()

return
int index of highest-numbered record currently in use

    return lastUsed;
  
intspecialFind(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;
  
voidwriteEntry(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

param
position int Record number
param
offset int Column number
param
value int New contents

    /*
    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!
    }
  
voidwriteSlot(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.

param
position integer Record number
param
w0 int
param
w1 int
param
w2 int
param
w3 int

      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;