home *** CD-ROM | disk | FTP | other *** search
/ Java 1.2 How-To / JavaHowTo.iso / 3rdParty / jbuilder / unsupported / JDK1.2beta3 / SOURCE / SRC.ZIP / java / awt / font / CompactByteArray.java < prev    next >
Encoding:
Java Source  |  1998-03-20  |  13.7 KB  |  391 lines

  1. /*
  2.  * @(#)CompactByteArray.java    1.3 98/03/18
  3.  *
  4.  * Copyright 1997, 1998 by Sun Microsystems, Inc.,
  5.  * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
  6.  * All rights reserved.
  7.  *
  8.  * This software is the confidential and proprietary information
  9.  * of Sun Microsystems, Inc. ("Confidential Information").  You
  10.  * shall not disclose such Confidential Information and shall use
  11.  * it only in accordance with the terms of the license agreement
  12.  * you entered into with Sun.
  13.  */
  14.  
  15. /*
  16.  * (C) Copyright Taligent, Inc. 1996 - 1997, All Rights Reserved
  17.  * (C) Copyright IBM Corp. 1996 - 1998, All Rights Reserved
  18.  *
  19.  * The original version of this source code and documentation is
  20.  * copyrighted and owned by Taligent, Inc., a wholly-owned subsidiary
  21.  * of IBM. These materials are provided under terms of a License
  22.  * Agreement between Taligent and Sun. This technology is protected
  23.  * by multiple US and International patents.
  24.  *
  25.  * This notice and attribution to Taligent may not be removed.
  26.  * Taligent is a registered trademark of Taligent, Inc.
  27.  *
  28.  */
  29.  
  30. package java.awt.font;
  31.  
  32. /**
  33.  * class CompactATypeArray : use only on primitive data types
  34.  * Provides a compact way to store information that is indexed by Unicode
  35.  * values, such as character properties, types, keyboard values, etc.This
  36.  * is very useful when you have a block of Unicode data that contains
  37.  * significant values while the rest of the Unicode data is unused in the
  38.  * application or when you have a lot of redundance, such as where all 21,000
  39.  * Han ideographs have the same value.  However, lookup is much faster than a
  40.  * hash table.
  41.  * A compact array of any primitive data type serves two purposes:
  42.  * <UL type = round>
  43.  *     <LI>Fast access of the indexed values.
  44.  *     <LI>Smaller memory footprint.
  45.  * </UL>
  46.  * A compact array is composed of a index array and value array.  The index
  47.  * array contains the indicies of Unicode characters to the value array.
  48.  *
  49.  * @see                CompactCharArray
  50.  * @see                CompactIntArray
  51.  * @see                CompactShortArray
  52.  * @see                CompactStringArray
  53.  * @version            1.1 7/15/97
  54.  * @author             Helena Shih
  55.  */
  56.  
  57.  // {jbr} CompactByteArray - temporary
  58.  
  59. final class CompactByteArray implements Cloneable {
  60.  
  61.     /**
  62.      * The total number of Unicode characters.
  63.      */
  64.     public static  final int UNICODECOUNT =65536;
  65.  
  66.     /**
  67.      * Default constructor for CompactByteArray, the default value of the
  68.      * compact array is 0.
  69.      */
  70.     public CompactByteArray() {
  71.         this((byte)0);
  72.     }
  73.     /**
  74.      * Constructor for CompactByteArray.
  75.      * @param defaultValue the default value of the compact array.
  76.      */
  77.     public CompactByteArray(byte defaultValue) {
  78.         int i;
  79.         values = new byte[UNICODECOUNT];
  80.         indices = new short[INDEXCOUNT];
  81.         for (i = 0; i < UNICODECOUNT; ++i) {
  82.             values[i] = defaultValue;
  83.         }
  84.         for (i = 0; i < INDEXCOUNT; ++i) {
  85.             indices[i] = (short)(i<<BLOCKSHIFT);
  86.         }
  87.         isCompact = false;
  88.     }
  89.     /**
  90.      * Constructor for CompactByteArray.
  91.      * @param indexArray the indicies of the compact array.
  92.      * @param newValues the values of the compact array.
  93.      * @exception IllegalArgumentException If index is out of range.
  94.      */
  95.     public CompactByteArray(short indexArray[],
  96.                             byte newValues[]) {
  97.         int i;
  98.         if (indexArray.length != INDEXCOUNT)
  99.             throw new IllegalArgumentException("Index out of bounds!");
  100.         for (i = 0; i < INDEXCOUNT; ++i) {
  101.             short index = indexArray[i];
  102.             if ((index < 0) || (index >= newValues.length+BLOCKCOUNT))
  103.                 throw new IllegalArgumentException("Index out of bounds!");
  104.         }
  105.         indices = indexArray;
  106.         values = newValues;
  107.         isCompact = false;
  108.     }
  109.     /**
  110.      * Get the mapped value of a Unicode character.
  111.      * @param index the character to get the mapped value with
  112.      * @return the mapped value of the given character
  113.      */
  114.     public byte elementAt(char index) {
  115.         return (values[(indices[index >> BLOCKSHIFT] & 0xFFFF)
  116.                        + (index & BLOCKMASK)]);
  117.     }
  118.     /**
  119.      * Set a new value for a Unicode character.
  120.      * Set automatically expands the array if it is compacted.
  121.      * @param index the character to set the mapped value with
  122.      * @param value the new mapped value
  123.      */
  124.     public void setElementAt(char index, byte value) {
  125.         if (isCompact)
  126.             expand();
  127.         values[(int)index] = value;
  128.     }
  129.     /**
  130.      * Set new values for a range of Unicode character.
  131.      * @param start the starting offset of the range
  132.      * @param end the ending offset of the range
  133.      * @param value the new mapped value
  134.      */
  135.     public void setElementAt(char start, char end, byte value) {
  136.         int i;
  137.         if (isCompact) {
  138.             expand();
  139.         }
  140.         for (i = start; i <= end; ++i) {
  141.             values[i] = value;
  142.         }
  143.     }
  144.     /**
  145.       *Compact the array.
  146.       */
  147.     public void compact() {
  148.         if (isCompact == false) {
  149.             char[]      tempIndex;
  150.             int                     tempIndexCount;
  151.             byte[]          tempArray;
  152.             short           iBlock, iIndex;
  153.  
  154.             // make temp storage, larger than we need
  155.             tempIndex = new char[UNICODECOUNT];
  156.             // set up first block.
  157.             tempIndexCount = BLOCKCOUNT;
  158.             for (iIndex = 0; iIndex < BLOCKCOUNT; ++iIndex) {
  159.                 tempIndex[iIndex] = (char)iIndex;
  160.             }; // endfor (iIndex = 0; .....)
  161.             indices[0] = (short)0;
  162.  
  163.             // for each successive block, find out its first position
  164.             // in the compacted array
  165.             for (iBlock = 1; iBlock < INDEXCOUNT; ++iBlock) {
  166.                 int     newCount, firstPosition, block;
  167.                 block = iBlock<<BLOCKSHIFT;
  168.                 if (DEBUGSMALL) if (block > DEBUGSMALLLIMIT) break;
  169.                 firstPosition = FindOverlappingPosition( block, tempIndex,
  170.                                                          tempIndexCount );
  171.  
  172.                 newCount = firstPosition + BLOCKCOUNT;
  173.                 if (newCount > tempIndexCount) {
  174.                     for (iIndex = (short)tempIndexCount;
  175.                          iIndex < newCount;
  176.                          ++iIndex) {
  177.                         tempIndex[iIndex] = (char)
  178.                                             (iIndex - firstPosition + block);
  179.                     } // endfor (iIndex = tempIndexCount....)
  180.                     tempIndexCount = newCount;
  181.                 } // endif (newCount > tempIndexCount)
  182.                 indices[iBlock] = (short)firstPosition;
  183.             } // endfor (iBlock = 1.....)
  184.  
  185.             // now allocate and copy the items into the array
  186.             tempArray = new byte[tempIndexCount];
  187.             for (iIndex = 0; iIndex < tempIndexCount; ++iIndex) {
  188.                 tempArray[iIndex] = values[tempIndex[iIndex]];
  189.             }
  190.             values = null;
  191.             values = tempArray;
  192.             isCompact = true;
  193.         } // endif (isCompact != false)
  194.     }
  195.     /** For internal use only.  Do not modify the result, the behavior of
  196.       * modified results are undefined.
  197.       */
  198.     public short getIndexArray()[]
  199.     {
  200.         return indices;
  201.     }
  202.     /** For internal use only.  Do not modify the result, the behavior of
  203.       * modified results are undefined.
  204.       */
  205.     public byte getStringArray()[]
  206.     {
  207.         return values;
  208.     }
  209.     /**
  210.      * Overrides Cloneable
  211.      */
  212.     public Object clone() {
  213.         try {
  214.             CompactByteArray other = (CompactByteArray) super.clone();
  215.             other.values = (byte[])values.clone();
  216.             other.indices = (short[])indices.clone();
  217.             return other;
  218.         } catch (CloneNotSupportedException e) {
  219.             throw new InternalError();
  220.         }
  221.     }
  222.     /**
  223.      * Compares the equality of two compact array objects.
  224.      * @param obj the compact array object to be compared with this.
  225.      * @return true if the current compact array object is the same
  226.      * as the compact array object obj; false otherwise.
  227.      */
  228.     public boolean equals(Object obj) {
  229.         if (this == obj)                      // quick check
  230.             return true;
  231.         if (getClass() != obj.getClass())         // same class?
  232.             return false;
  233.         CompactByteArray other = (CompactByteArray) obj;
  234.         for (int i = 0; i < UNICODECOUNT; i++) {
  235.             // could be sped up later
  236.             if (elementAt((char)i) != other.elementAt((char)i))
  237.                 return false;
  238.         }
  239.         return true; // we made it through the guantlet.
  240.     }
  241.  
  242.     /**
  243.      * Generates the hash code for the compact array object
  244.      */
  245.  
  246.     public int hashCode() {
  247.         int result = 0;
  248.         int increment = Math.min(3, values.length/16);
  249.         for (int i = 0; i < values.length; i+= increment) {
  250.             result = result * 37 + values[i];
  251.         }
  252.         return result;
  253.     }
  254.     // --------------------------------------------------------------
  255.     // package private
  256.     // --------------------------------------------------------------
  257.     void writeArrays() {
  258.         int i;
  259.         int cnt = (values.length > 0) ? values.length :
  260.             values.length+UNICODECOUNT;
  261.         System.out.println("{");
  262.         for (i = 0; i < INDEXCOUNT-1; i++)
  263.         {
  264.             System.out.print("(short)"
  265.                              + ((indices[i] >= 0) ?
  266.                                 (int)indices[i] :
  267.                                 (int)(indices[i]+UNICODECOUNT))
  268.                              + ", ");
  269.             if (i != 0)
  270.                 if (i % 10 == 0)
  271.                     System.out.println();
  272.         }
  273.         System.out.println("(short)"
  274.                            + ((indices[INDEXCOUNT-1] >= 0) ?
  275.                               (int)indices[i] :
  276.                               (int)(indices[i]+UNICODECOUNT))
  277.                            + " }");
  278.         System.out.println("{");
  279.         for (i = 0; i < cnt-1; i++)
  280.         {
  281.             System.out.print("(byte)" + (int)values[i] + ", ");
  282.             if (i != 0)
  283.                 if (i % 10 == 0)
  284.                     System.out.println();
  285.         }
  286.         System.out.println("(byte)" + (int)values[cnt-1] + " }");
  287.     }
  288.     // Print char Array  : Debug only
  289.     void printIndex(short start, short count) {
  290.         int i;
  291.         for (i = start; i < count; ++i)
  292.         {
  293.             System.out.println(i + " -> : " +
  294.                                (int)((indices[i] >= 0) ?
  295.                                      indices[i] :
  296.                                      indices[i] + UNICODECOUNT));
  297.         }
  298.         System.out.println();
  299.     }
  300.     void printPlainArray(int start,int count, char[] tempIndex) {
  301.         int iIndex;
  302.         if (tempIndex != null)
  303.         {
  304.             for (iIndex     = start; iIndex < start + count; ++iIndex)
  305.             {
  306.                 System.out.print(" " + (int)values[tempIndex[iIndex]]);
  307.             }
  308.         }
  309.         else
  310.         {
  311.             for (iIndex = start; iIndex < start + count; ++iIndex)
  312.             {
  313.                 System.out.print(" " + (int)values[iIndex]);
  314.             }
  315.         }
  316.         System.out.println("    Range: start " + start + " , count " + count);
  317.     }
  318.     // --------------------------------------------------------------
  319.     // private
  320.     // --------------------------------------------------------------
  321.     /**
  322.       * Expanding takes the array back to a 65536 element array.
  323.       */
  324.     private void expand() {
  325.         int i;
  326.         if (isCompact) {
  327.             byte[]  tempArray;
  328.             tempArray = new byte[UNICODECOUNT];
  329.             for (i = 0; i < UNICODECOUNT; ++i) {
  330.                 tempArray[i] = elementAt((char)i);
  331.             }
  332.             for (i = 0; i < INDEXCOUNT; ++i) {
  333.                 indices[i] = (short)(i<<BLOCKSHIFT);
  334.             }
  335.             values = null;
  336.             values = tempArray;
  337.             isCompact = false;
  338.         }
  339.     }
  340.     // # of elements in the indexed array
  341.     private short capacity() {
  342.         return (short)values.length;
  343.     }
  344.     private byte[] getArray() {
  345.         return values;
  346.     }
  347.     private int
  348.     FindOverlappingPosition(int start, char[] tempIndex, int tempIndexCount) {
  349.         int i;
  350.         short j;
  351.         short currentCount;
  352.  
  353.         if (DEBUGOVERLAP && start < DEBUGSHOWOVERLAPLIMIT) {
  354.             printPlainArray(start, BLOCKCOUNT, null);
  355.             printPlainArray(0, tempIndexCount, tempIndex);
  356.         }
  357.         for (i = 0; i < tempIndexCount; i += BLOCKCOUNT) {
  358.             currentCount = (short)BLOCKCOUNT;
  359.             if (i + BLOCKCOUNT > tempIndexCount) {
  360.                 currentCount = (short)(tempIndexCount - i);
  361.             }
  362.             for (j = 0; j < currentCount; ++j) {
  363.                 if (values[start + j] != values[tempIndex[i + j]]) break;
  364.             }
  365.             if (j == currentCount) break;
  366.         }
  367.         if (DEBUGOVERLAP && start < DEBUGSHOWOVERLAPLIMIT) {
  368.             for (j = 1; j < i; ++j) {
  369.                 System.out.print(" ");
  370.             }
  371.             printPlainArray(start, BLOCKCOUNT, null);
  372.             System.out.println("    Found At: " + i);
  373.         }
  374.         return i;
  375.     }
  376.     private static  final int DEBUGSHOWOVERLAPLIMIT = 100;
  377.     private static  final boolean DEBUGTRACE = false;
  378.     private static  final boolean DEBUGSMALL = false;
  379.     private static  final boolean DEBUGOVERLAP = false;
  380.     private static  final int DEBUGSMALLLIMIT = 30000;
  381.     private static  final int BLOCKSHIFT =7;
  382.     private static  final int BLOCKCOUNT =(1<<BLOCKSHIFT);
  383.     private static  final int INDEXSHIFT =(16-BLOCKSHIFT);
  384.     private static  final int INDEXCOUNT =(1<<INDEXSHIFT);
  385.     private static  final int BLOCKMASK = BLOCKCOUNT - 1;
  386.  
  387.     private byte[] values;  // char -> short (char parameterized short)
  388.     private short indices[];
  389.     private boolean isCompact;
  390. };
  391.