/* * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package build.tools.generatebreakiteratordata; import java.util.Arrays; final class SupplementaryCharacterData { /** * Default value */ private static final byte DEFAULT_VALUE = 0; private byte defaultValue; /** * A array which has a unicode code point(0x010000-0x10FFFF) as the upper * 3 bytes and a value as the remaining one byte in each data. */ private int[] dataTable; /* * Counter to keep the number of data in tempTable */ private int dataCount; /* * Temporary data table used until dataTable is generated. */ private long[] tempTable; /* * Initila tempTable size */ private static final int INITIAL_TABLE_SIZE = 150; /* * The number of entries to be appended when tempTable becomes full */ private static final int ADDITIONAL_TABLE_SIZE = 10; /* * Upper limit, used as a sentinel */ private static final int UPPER_LIMIT = Character.MAX_CODE_POINT + 1; /* * Mask for supplementary code points(0x010000-0x10FFFF) */ private static final int CODEPOINT_MASK = 0x1FFFFF; public SupplementaryCharacterData(byte value) { defaultValue = value; dataCount = 0; } /** * Appends the given data to tempTable */ public void appendElement(int start, int end, byte value) { if (tempTable == null) { tempTable = new long[INITIAL_TABLE_SIZE]; } if (dataCount == tempTable.length) { long[] tempTempTable = new long[dataCount + ADDITIONAL_TABLE_SIZE]; System.arraycopy(tempTable, 0, tempTempTable, 0, dataCount); tempTable = tempTempTable; } tempTable[dataCount++] = ((((long)start<<24) + end)<<8) + value; } /** * Returns the data table */ public int[] getArray() { return dataTable; } /** * Creates dataTable */ public void complete() { dataTable = generateTable(); } /** * Generates a table from the given data */ private int[] generateTable() { /* If tempTable is empty, put two data */ if (dataCount == 0) { int[] tmpArray = new int[2]; tmpArray[0] = composeEntry(0, DEFAULT_VALUE); tmpArray[1] = composeEntry(UPPER_LIMIT, DEFAULT_VALUE); tempTable = null; return tmpArray; } Arrays.sort(tempTable, 0, dataCount); int[] newTempTable = new int[dataCount*2 + 3]; int old_index = 0; int new_index = 0; int loop_count = dataCount - 1; long data = tempTable[old_index]; int start = (int)(data>>32) & CODEPOINT_MASK; int end = (int)(data>>8) & CODEPOINT_MASK; /* * Add an entry if the first start code point in tempTable is not * the minimum supplementary code point. */ if (start != Character.MIN_SUPPLEMENTARY_CODE_POINT) { newTempTable[new_index++] = composeEntry(Character.MIN_SUPPLEMENTARY_CODE_POINT, defaultValue); } newTempTable[new_index++] = composeEntry(start, (int)data); for (int i = 0; i < loop_count; i++) { data = tempTable[++old_index]; int nextStart = (int)(data>>32) & CODEPOINT_MASK; /* * If the previous end code point is not equal to the previous start * code point and is not consecutive with the next start code point, * insert a filler entry before an entry for the next start code * point. */ if (end != start && end != nextStart-1) { newTempTable[new_index++] = composeEntry(end + 1, defaultValue); } newTempTable[new_index++] = composeEntry(nextStart, (int)data); start = nextStart; end = (int)(data>>8) & CODEPOINT_MASK; } newTempTable[new_index++] = composeEntry(++end, defaultValue); /* Add an entry for a sentinel if necessary. */ if (end < UPPER_LIMIT) { newTempTable[new_index++] = composeEntry(UPPER_LIMIT, defaultValue); } /* Copy data to dataTable. */ dataTable = new int[new_index]; System.arraycopy(newTempTable, 0, dataTable, 0, new_index); tempTable = null; return dataTable; } /** * Composes an entry with the given supplementary code point * (0x010000-0x10FFFF) for the upper 3 bytes and the given value for the * remaining one byte. */ private int composeEntry(int codePoint, int value) { return (codePoint<<8) | (value&0xFF); } }