19f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson/*
29f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Licensed to the Apache Software Foundation (ASF) under one
39f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * or more contributor license agreements. See the NOTICE file
49f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * distributed with this work for additional information
59f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * regarding copyright ownership. The ASF licenses this file
69f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * to you under the Apache License, Version 2.0 (the  "License");
79f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * you may not use this file except in compliance with the License.
89f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * You may obtain a copy of the License at
99f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson *
109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson *     http://www.apache.org/licenses/LICENSE-2.0
119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson *
129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Unless required by applicable law or agreed to in writing, software
139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * distributed under the License is distributed on an "AS IS" BASIS,
149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * See the License for the specific language governing permissions and
169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * limitations under the License.
179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */
189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson/*
199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * $Id: ChunkedIntArray.java 468653 2006-10-28 07:07:05Z minchau $
209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */
219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonpackage org.apache.xml.dtm.ref;
229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.apache.xml.res.XMLErrorResources;
249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.apache.xml.res.XMLMessages;
259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson/**
279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * <code>ChunkedIntArray</code> is an extensible array of blocks of integers.
289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * (I'd consider Vector, but it's unable to handle integers except by
299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * turning them into Objects.)
309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * <p>Making this a separate class means some call-and-return overhead. But
329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * doing it all inline tends to be fragile and expensive in coder time,
339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * not to mention driving up code size. If you want to inline it, feel free.
349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * The Java text suggest that private and Final methods may be inlined,
359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * and one can argue that this beast need not be made subclassable...</p>
369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson *
379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * <p>%REVIEW% This has strong conceptual overlap with the IntVector class.
389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * It would probably be a good thing to merge the two, when time permits.<p>
399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */
409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonfinal class ChunkedIntArray
419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson{
429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  final int slotsize=4; // Locked, MUST be power of two in current code
439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  // Debugging tip: Cranking lowbits down to 4 or so is a good
449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  // way to pound on the array addressing code.
459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  static final int lowbits=10; // How many bits address within chunks
469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  static final int chunkalloc=1<<lowbits;
479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  static final int lowmask=chunkalloc-1;
489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  ChunksVector chunks=new ChunksVector();
509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  final int fastArray[] = new int[chunkalloc];
519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  int lastUsed=0;
529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Create a new CIA with specified record size. Currently record size MUST
559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * be a power of two... and in fact is hardcoded to 4.
569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  ChunkedIntArray(int slotsize)
589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if(this.slotsize<slotsize)
609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      throw new ArrayIndexOutOfBoundsException(XMLMessages.createXMLMessage(XMLErrorResources.ER_CHUNKEDINTARRAY_NOT_SUPPORTED, new Object[]{Integer.toString(slotsize)})); //"ChunkedIntArray("+slotsize+") not currently supported");
619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    else if (this.slotsize>slotsize)
629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      System.out.println("*****WARNING: ChunkedIntArray("+slotsize+") wasting "+(this.slotsize-slotsize)+" words per slot");
639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    chunks.addElement(fastArray);
649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Append a 4-integer record to the CIA, starting with record 1. (Since
679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * arrays are initialized to all-0, 0 has been reserved as the "unknown"
689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * value in DTM.)
699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @return the index at which this record was inserted.
709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  int appendSlot(int w0, int w1, int w2, int w3)
729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    /*
749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    try
759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      int newoffset = (lastUsed+1)*slotsize;
779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      fastArray[newoffset] = w0;
789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      fastArray[newoffset+1] = w1;
799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      fastArray[newoffset+2] = w2;
809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      fastArray[newoffset+3] = w3;
819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      return ++lastUsed;
829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    catch(ArrayIndexOutOfBoundsException aioobe)
849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    */
859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      final int slotsize=4;
879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      int newoffset = (lastUsed+1)*slotsize;
889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      int chunkpos = newoffset >> lowbits;
899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      int slotpos = (newoffset & lowmask);
909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      // Grow if needed
929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      if (chunkpos > chunks.size() - 1)
939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        chunks.addElement(new int[chunkalloc]);
949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      int[] chunk = chunks.elementAt(chunkpos);
959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      chunk[slotpos] = w0;
969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      chunk[slotpos+1] = w1;
979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      chunk[slotpos+2] = w2;
989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      chunk[slotpos+3] = w3;
999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      return ++lastUsed;
1019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
1029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
1039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
1049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Retrieve an integer from the CIA by record number and column within
1059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * the record, both 0-based (though position 0 is reserved for special
1069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * purposes).
1079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param position int Record number
1089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param slotpos int Column number
1099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
1109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  int readEntry(int position, int offset) throws ArrayIndexOutOfBoundsException
1119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
1129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    /*
1139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    try
1149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
1159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      return fastArray[(position*slotsize)+offset];
1169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
1179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    catch(ArrayIndexOutOfBoundsException aioobe)
1189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    */
1199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
1209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      // System.out.println("Using slow read (1)");
1219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      if (offset>=slotsize)
1229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        throw new ArrayIndexOutOfBoundsException(XMLMessages.createXMLMessage(XMLErrorResources.ER_OFFSET_BIGGER_THAN_SLOT, null)); //"Offset bigger than slot");
1239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      position*=slotsize;
1249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      int chunkpos = position >> lowbits;
1259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      int slotpos = position & lowmask;
1269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      int[] chunk = chunks.elementAt(chunkpos);
1279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      return chunk[slotpos + offset];
1289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
1299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
1309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  // Check that the node at index "position" is not an ancestor
1329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  // of the node at index "startPos". IF IT IS, DO NOT ACCEPT IT AND
1339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  // RETURN -1. If position is NOT an ancestor, return position.
1349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  // Special case: The Document node (position==0) is acceptable.
1359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  //
1369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  // This test supports DTM.getNextPreceding.
1379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  int specialFind(int startPos, int position)
1389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
1399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          // We have to look all the way up the ancestor chain
1409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          // to make sure we don't have an ancestor.
1419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          int ancestor = startPos;
1429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          while(ancestor > 0)
1439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          {
1449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                // Get the node whose index == ancestor
1459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                ancestor*=slotsize;
1469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                int chunkpos = ancestor >> lowbits;
1479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                int slotpos = ancestor & lowmask;
1489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                int[] chunk = chunks.elementAt(chunkpos);
1499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                // Get that node's parent (Note that this assumes w[1]
1519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                // is the parent node index. That's really a DTM feature
1529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                // rather than a ChunkedIntArray feature.)
1539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                ancestor = chunk[slotpos + 1];
1549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                if(ancestor == position)
1569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                         break;
1579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          }
1589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          if (ancestor <= 0)
1609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          {
1619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                  return position;
1629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          }
1639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          return -1;
1649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
1659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
1679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @return int index of highest-numbered record currently in use
1689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
1699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  int slotsUsed()
1709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
1719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return lastUsed;
1729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
1739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /** Disard the highest-numbered record. This is used in the string-buffer
1759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   CIA; when only a single characters() chunk has been recieved, its index
1769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   is moved into the Text node rather than being referenced by indirection
1779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   into the text accumulator.
1789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
1799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  void discardLast()
1809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
1819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    --lastUsed;
1829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
1839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
1859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Overwrite the integer found at a specific record and column.
1869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Used to back-patch existing records, most often changing their
1879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * "next sibling" reference from 0 (unknown) to something meaningful
1889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param position int Record number
1899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param offset int Column number
1909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param value int New contents
1919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
1929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  void writeEntry(int position, int offset, int value) throws ArrayIndexOutOfBoundsException
1939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
1949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    /*
1959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    try
1969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
1979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      fastArray[( position*slotsize)+offset] = value;
1989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
1999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    catch(ArrayIndexOutOfBoundsException aioobe)
2009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    */
2019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
2029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      if (offset >= slotsize)
2039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        throw new ArrayIndexOutOfBoundsException(XMLMessages.createXMLMessage(XMLErrorResources.ER_OFFSET_BIGGER_THAN_SLOT, null)); //"Offset bigger than slot");
2049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      position*=slotsize;
2059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      int chunkpos = position >> lowbits;
2069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      int slotpos = position & lowmask;
2079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      int[] chunk = chunks.elementAt(chunkpos);
2089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      chunk[slotpos + offset] = value; // ATOMIC!
2099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
2109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
2119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
2139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Overwrite an entire (4-integer) record at the specified index.
2149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Mostly used to create record 0, the Document node.
2159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param position integer Record number
2169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param w0 int
2179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param w1 int
2189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param w2 int
2199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param w3 int
2209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
2219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  void writeSlot(int position, int w0, int w1, int w2, int w3)
2229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
2239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      position *= slotsize;
2249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      int chunkpos = position >> lowbits;
2259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      int slotpos = (position & lowmask);
2269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // Grow if needed
2289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (chunkpos > chunks.size() - 1)
2299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      chunks.addElement(new int[chunkalloc]);
2309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    int[] chunk = chunks.elementAt(chunkpos);
2319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    chunk[slotpos] = w0;
2329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    chunk[slotpos + 1] = w1;
2339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    chunk[slotpos + 2] = w2;
2349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    chunk[slotpos + 3] = w3;
2359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
2369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
2389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Retrieve the contents of a record into a user-supplied buffer array.
2399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Used to reduce addressing overhead when code will access several
2409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * columns of the record.
2419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param position int Record number
2429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param buffer int[] Integer array provided by user, must be large enough
2439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * to hold a complete record.
2449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
2459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  void readSlot(int position, int[] buffer)
2469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
2479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    /*
2489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    try
2499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
2509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      System.arraycopy(fastArray, position*slotsize, buffer, 0, slotsize);
2519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
2529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    catch(ArrayIndexOutOfBoundsException aioobe)
2539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    */
2549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
2559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      // System.out.println("Using slow read (2): "+position);
2569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      position *= slotsize;
2579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      int chunkpos = position >> lowbits;
2589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      int slotpos = (position & lowmask);
2599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      // Grow if needed
2619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      if (chunkpos > chunks.size() - 1)
2629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        chunks.addElement(new int[chunkalloc]);
2639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      int[] chunk = chunks.elementAt(chunkpos);
2649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      System.arraycopy(chunk,slotpos,buffer,0,slotsize);
2659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
2669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
2679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  class ChunksVector
2699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
2709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    final int BLOCKSIZE = 64;
2719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    int[] m_map[] = new int[BLOCKSIZE][];
2729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    int m_mapSize = BLOCKSIZE;
2739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    int pos = 0;
2749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    ChunksVector()
2769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
2779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
2789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    final int size()
2809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
2819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      return pos;
2829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
2839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    void addElement(int[] value)
2859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
2869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      if(pos >= m_mapSize)
2879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
2889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        int orgMapSize = m_mapSize;
2899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        while(pos >= m_mapSize)
2909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          m_mapSize+=BLOCKSIZE;
2919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        int[] newMap[] = new int[m_mapSize][];
2929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        System.arraycopy(m_map, 0, newMap, 0, orgMapSize);
2939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        m_map = newMap;
2949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
2959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      // For now, just do a simple append.  A sorted insert only
2969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      // makes sense if we're doing an binary search or some such.
2979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      m_map[pos] = value;
2989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      pos++;
2999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
3009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    final int[] elementAt(int pos)
3029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
3039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      return m_map[pos];
3049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
3059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
3069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson}
307