| /* |
| * Copyright (c) 2003, 2013, 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); |
| } |
| } |