chunkedintarray.java

来自「java jdk 1.4的源码」· Java 代码 · 共 346 行

JAVA
346
字号
/* * The Apache Software License, Version 1.1 * * * Copyright (c) 1999 The Apache Software Foundation.  All rights  * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer.  * * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in *    the documentation and/or other materials provided with the *    distribution. * * 3. The end-user documentation included with the redistribution, *    if any, must include the following acknowledgment:   *       "This product includes software developed by the *        Apache Software Foundation (http://www.apache.org/)." *    Alternately, this acknowledgment may appear in the software itself, *    if and wherever such third-party acknowledgments normally appear. * * 4. The names "Xalan" and "Apache Software Foundation" must *    not be used to endorse or promote products derived from this *    software without prior written permission. For written  *    permission, please contact apache@apache.org. * * 5. Products derived from this software may not be called "Apache", *    nor may "Apache" appear in their name, without prior written *    permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation and was * originally based on software copyright (c) 1999, Lotus * Development Corporation., http://www.lotus.com.  For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */package org.apache.xml.dtm.ref; import org.w3c.dom.*;import org.apache.xml.dtm.*;import org.apache.xalan.res.XSLTErrorResources;import org.apache.xalan.res.XSLMessages;/** * <code>ChunkedIntArray</code> 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.) * <p>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...</p> * * <p>%REVIEW% This has strong conceptual overlap with the IntVector class. * It would probably be a good thing to merge the two, when time permits.<p> */final class ChunkedIntArray{  final int slotsize=4; // Locked, MUST be power of two in current code  // Debugging tip: Cranking lowbits down to 4 or so is a good  // way to pound on the array addressing code.  static final int lowbits=10; // How many bits address within chunks  static final int chunkalloc=1<<lowbits;  static final int lowmask=chunkalloc-1;    ChunksVector chunks=new ChunksVector();  final int fastArray[] = new int[chunkalloc];  int lastUsed=0;  /**   * Create a new CIA with specified record size. Currently record size MUST   * be a power of two... and in fact is hardcoded to 4.   */  ChunkedIntArray(int slotsize)  {    if(this.slotsize<slotsize)      throw new ArrayIndexOutOfBoundsException(XSLMessages.createMessage(XSLTErrorResources.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);  }  /**   * 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.   */  int appendSlot(int w0, int w1, int w2, int w3)  {    /*    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;    }  }  /**   * 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   */  int readEntry(int position, int offset) throws ArrayIndexOutOfBoundsException  {    /*    try    {      return fastArray[(position*slotsize)+offset];    }    catch(ArrayIndexOutOfBoundsException aioobe)    */    {      // System.out.println("Using slow read (1)");      if (offset>=slotsize)        throw new ArrayIndexOutOfBoundsException(XSLMessages.createMessage(XSLTErrorResources.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];    }  }    // Check that the node at index "position" is not an ancestor  // of the node at index "startPos". IF IT IS, DO NOT ACCEPT IT AND  // RETURN -1. If position is NOT an ancestor, return position.  // Special case: The Document node (position==0) is acceptable.  //  // This test supports DTM.getNextPreceding.  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;  }    /**   * @return int index of highest-numbered record currently in use   */  int slotsUsed()  {    return lastUsed;  }  /** 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.   */  void discardLast()  {    --lastUsed;  }  /**   * 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   */  void writeEntry(int position, int offset, int value) throws ArrayIndexOutOfBoundsException  {    /*    try    {      fastArray[( position*slotsize)+offset] = value;    }    catch(ArrayIndexOutOfBoundsException aioobe)    */    {      if (offset >= slotsize)        throw new ArrayIndexOutOfBoundsException(XSLMessages.createMessage(XSLTErrorResources.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!    }  }  /**   * 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   */  void writeSlot(int position, int w0, int w1, int w2, int w3)  {      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;  }  /**   * 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.   */  void readSlot(int position, int[] buffer)  {    /*    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);    }  }  class ChunksVector  {    final int BLOCKSIZE = 64;    int[] m_map[] = new int[BLOCKSIZE][];    int m_mapSize = BLOCKSIZE;    int pos = 0;        ChunksVector()    {    }        final int size()    {      return pos;    }        void addElement(int[] value)    {      if(pos >= m_mapSize)      {        int orgMapSize = m_mapSize;        while(pos >= m_mapSize)          m_mapSize+=BLOCKSIZE;        int[] newMap[] = new int[m_mapSize][];        System.arraycopy(m_map, 0, newMap, 0, orgMapSize);        m_map = newMap;      }      // For now, just do a simple append.  A sorted insert only       // makes sense if we're doing an binary search or some such.      m_map[pos] = value;      pos++;    }        final int[] elementAt(int pos)    {      return m_map[pos];    }  }}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?