| 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 */  | 
 | 
 | 
 | 
package sun.text;  | 
 | 
 | 
 | 
public final class UCompactIntArray implements Cloneable { | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public UCompactIntArray() { | 
 | 
        values = new int[16][];  | 
 | 
        indices = new short[16][];  | 
 | 
        blockTouched = new boolean[16][];  | 
 | 
        planeTouched = new boolean[16];  | 
 | 
    }  | 
 | 
 | 
 | 
    public UCompactIntArray(int defaultValue) { | 
 | 
        this();  | 
 | 
        this.defaultValue = defaultValue;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public int elementAt(int index) { | 
 | 
        int plane = (index & PLANEMASK) >> PLANESHIFT;  | 
 | 
        if (!planeTouched[plane]) { | 
 | 
            return defaultValue;  | 
 | 
        }  | 
 | 
        index &= CODEPOINTMASK;  | 
 | 
        return values[plane][(indices[plane][index >> BLOCKSHIFT] & 0xFFFF)  | 
 | 
                       + (index & BLOCKMASK)];  | 
 | 
    }  | 
 | 
 | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public void setElementAt(int index, int value) { | 
 | 
        if (isCompact) { | 
 | 
            expand();  | 
 | 
        }  | 
 | 
        int plane = (index & PLANEMASK) >> PLANESHIFT;  | 
 | 
        if (!planeTouched[plane]) { | 
 | 
            initPlane(plane);  | 
 | 
        }  | 
 | 
        index &= CODEPOINTMASK;  | 
 | 
        values[plane][index] = value;  | 
 | 
        blockTouched[plane][index >> BLOCKSHIFT] = true;  | 
 | 
    }  | 
 | 
 | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    public void compact() { | 
 | 
        if (isCompact) { | 
 | 
            return;  | 
 | 
        }  | 
 | 
        for (int plane = 0; plane < PLANECOUNT; plane++) { | 
 | 
            if (!planeTouched[plane]) { | 
 | 
                continue;  | 
 | 
            }  | 
 | 
            int limitCompacted = 0;  | 
 | 
            int iBlockStart = 0;  | 
 | 
            short iUntouched = -1;  | 
 | 
 | 
 | 
            for (int i = 0; i < indices[plane].length; ++i, iBlockStart += BLOCKCOUNT) { | 
 | 
                indices[plane][i] = -1;  | 
 | 
                if (!blockTouched[plane][i] && iUntouched != -1) { | 
 | 
                    // If no values in this block were set, we can just set its  | 
 | 
                    // index to be the same as some other block with no values  | 
 | 
                      | 
 | 
                    indices[plane][i] = iUntouched;  | 
 | 
                } else { | 
 | 
                    int jBlockStart = limitCompacted * BLOCKCOUNT;  | 
 | 
                    if (i > limitCompacted) { | 
 | 
                        System.arraycopy(values[plane], iBlockStart,  | 
 | 
                                         values[plane], jBlockStart, BLOCKCOUNT);  | 
 | 
                    }  | 
 | 
                    if (!blockTouched[plane][i]) { | 
 | 
                          | 
 | 
                        iUntouched = (short)jBlockStart;  | 
 | 
                    }  | 
 | 
                    indices[plane][i] = (short)jBlockStart;  | 
 | 
                    limitCompacted++;  | 
 | 
                }  | 
 | 
            }  | 
 | 
 | 
 | 
              | 
 | 
            int newSize = limitCompacted * BLOCKCOUNT;  | 
 | 
            int[] result = new int[newSize];  | 
 | 
            System.arraycopy(values[plane], 0, result, 0, newSize);  | 
 | 
            values[plane] = result;  | 
 | 
            blockTouched[plane] = null;  | 
 | 
        }  | 
 | 
        isCompact = true;  | 
 | 
    }  | 
 | 
 | 
 | 
 | 
 | 
    // --------------------------------------------------------------  | 
 | 
    // private  | 
 | 
    // --------------------------------------------------------------  | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    private void expand() { | 
 | 
        int i;  | 
 | 
        if (isCompact) { | 
 | 
            int[]   tempArray;  | 
 | 
            for (int plane = 0; plane < PLANECOUNT; plane++) { | 
 | 
                if (!planeTouched[plane]) { | 
 | 
                    continue;  | 
 | 
                }  | 
 | 
                blockTouched[plane] = new boolean[INDEXCOUNT];  | 
 | 
                tempArray = new int[UNICODECOUNT];  | 
 | 
                for (i = 0; i < UNICODECOUNT; ++i) { | 
 | 
                    tempArray[i] = values[plane][indices[plane][i >> BLOCKSHIFT]  | 
 | 
                                                & 0xffff + (i & BLOCKMASK)];  | 
 | 
                    blockTouched[plane][i >> BLOCKSHIFT] = true;  | 
 | 
                }  | 
 | 
                for (i = 0; i < INDEXCOUNT; ++i) { | 
 | 
                    indices[plane][i] = (short)(i<<BLOCKSHIFT);  | 
 | 
                }  | 
 | 
                values[plane] = tempArray;  | 
 | 
            }  | 
 | 
            isCompact = false;  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    private void initPlane(int plane) { | 
 | 
        values[plane] = new int[UNICODECOUNT];  | 
 | 
        indices[plane] = new short[INDEXCOUNT];  | 
 | 
        blockTouched[plane] = new boolean[INDEXCOUNT];  | 
 | 
        planeTouched[plane] = true;  | 
 | 
 | 
 | 
        if (planeTouched[0] && plane != 0) { | 
 | 
            System.arraycopy(indices[0], 0, indices[plane], 0, INDEXCOUNT);  | 
 | 
        } else { | 
 | 
            for (int i = 0; i < INDEXCOUNT; ++i) { | 
 | 
                indices[plane][i] = (short)(i<<BLOCKSHIFT);  | 
 | 
            }  | 
 | 
        }  | 
 | 
        for (int i = 0; i < UNICODECOUNT; ++i) { | 
 | 
            values[plane][i] = defaultValue;  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    public int getKSize() { | 
 | 
        int size = 0;  | 
 | 
        for (int plane = 0; plane < PLANECOUNT; plane++) { | 
 | 
            if (planeTouched[plane]) { | 
 | 
                size += (values[plane].length * 4 + indices[plane].length * 2);  | 
 | 
            }  | 
 | 
        }  | 
 | 
        return size / 1024;  | 
 | 
    }  | 
 | 
 | 
 | 
    private static final int PLANEMASK = 0x30000;  | 
 | 
    private static final int PLANESHIFT = 16;  | 
 | 
    private static final int PLANECOUNT = 0x10;  | 
 | 
    private static final int CODEPOINTMASK  = 0xffff;  | 
 | 
 | 
 | 
    private static final int UNICODECOUNT = 0x10000;  | 
 | 
    private static final int BLOCKSHIFT = 7;  | 
 | 
    private static final int BLOCKCOUNT = (1<<BLOCKSHIFT);  | 
 | 
    private static final int INDEXSHIFT = (16-BLOCKSHIFT);  | 
 | 
    private static final int INDEXCOUNT = (1<<INDEXSHIFT);  | 
 | 
    private static final int BLOCKMASK = BLOCKCOUNT - 1;  | 
 | 
 | 
 | 
    private int defaultValue;  | 
 | 
    private int values[][];  | 
 | 
    private short indices[][];  | 
 | 
    private boolean isCompact;  | 
 | 
    private boolean[][] blockTouched;  | 
 | 
    private boolean[] planeTouched;  | 
 | 
};  |