Path: blob/master/src/java.base/share/classes/jdk/internal/icu/impl/Trie2.java
41161 views
/*1* Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425/*26*******************************************************************************27* Copyright (C) 2009-2014, International Business Machines Corporation and28* others. All Rights Reserved.29*******************************************************************************30*/3132package jdk.internal.icu.impl;3334import java.io.IOException;35import java.nio.ByteBuffer;36import java.nio.ByteOrder;37import java.util.Iterator;38import java.util.NoSuchElementException;394041/**42* This is the interface and common implementation of a Unicode Trie2.43* It is a kind of compressed table that maps from Unicode code points (0..0x10ffff)44* to 16- or 32-bit integer values. It works best when there are ranges of45* characters with the same value, which is generally the case with Unicode46* character properties.47*48* This is the second common version of a Unicode trie (hence the name Trie2).49*50*/51abstract class Trie2 implements Iterable<Trie2.Range> {5253/**54* Create a Trie2 from its serialized form. Inverse of utrie2_serialize().55*56* Reads from the current position and leaves the buffer after the end of the trie.57*58* The serialized format is identical between ICU4C and ICU4J, so this function59* will work with serialized Trie2s from either.60*61* The actual type of the returned Trie2 will be either Trie2_16 or Trie2_32, depending62* on the width of the data.63*64* To obtain the width of the Trie2, check the actual class type of the returned Trie2.65* Or use the createFromSerialized() function of Trie2_16 or Trie2_32, which will66* return only Tries of their specific type/size.67*68* The serialized Trie2 on the stream may be in either little or big endian byte order.69* This allows using serialized Tries from ICU4C without needing to consider the70* byte order of the system that created them.71*72* @param bytes a byte buffer to the serialized form of a UTrie2.73* @return An unserialized Trie2, ready for use.74* @throws IllegalArgumentException if the stream does not contain a serialized Trie2.75* @throws IOException if a read error occurs in the buffer.76*77*/78public static Trie2 createFromSerialized(ByteBuffer bytes) throws IOException {79// From ICU4C utrie2_impl.h80// * Trie2 data structure in serialized form:81// *82// * UTrie2Header header;83// * uint16_t index[header.index2Length];84// * uint16_t data[header.shiftedDataLength<<2]; -- or uint32_t data[...]85// * @internal86// */87// typedef struct UTrie2Header {88// /** "Tri2" in big-endian US-ASCII (0x54726932) */89// uint32_t signature;9091// /**92// * options bit field:93// * 15.. 4 reserved (0)94// * 3.. 0 UTrie2ValueBits valueBits95// */96// uint16_t options;97//98// /** UTRIE2_INDEX_1_OFFSET..UTRIE2_MAX_INDEX_LENGTH */99// uint16_t indexLength;100//101// /** (UTRIE2_DATA_START_OFFSET..UTRIE2_MAX_DATA_LENGTH)>>UTRIE2_INDEX_SHIFT */102// uint16_t shiftedDataLength;103//104// /** Null index and data blocks, not shifted. */105// uint16_t index2NullOffset, dataNullOffset;106//107// /**108// * First code point of the single-value range ending with U+10ffff,109// * rounded up and then shifted right by UTRIE2_SHIFT_1.110// */111// uint16_t shiftedHighStart;112// } UTrie2Header;113114ByteOrder outerByteOrder = bytes.order();115try {116UTrie2Header header = new UTrie2Header();117118/* check the signature */119header.signature = bytes.getInt();120switch (header.signature) {121case 0x54726932:122// The buffer is already set to the trie data byte order.123break;124case 0x32697254:125// Temporarily reverse the byte order.126boolean isBigEndian = outerByteOrder == ByteOrder.BIG_ENDIAN;127bytes.order(isBigEndian ? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN);128header.signature = 0x54726932;129break;130default:131throw new IllegalArgumentException("Buffer does not contain a serialized UTrie2");132}133134header.options = bytes.getChar();135header.indexLength = bytes.getChar();136header.shiftedDataLength = bytes.getChar();137header.index2NullOffset = bytes.getChar();138header.dataNullOffset = bytes.getChar();139header.shiftedHighStart = bytes.getChar();140141if ((header.options & UTRIE2_OPTIONS_VALUE_BITS_MASK) != 0) {142throw new IllegalArgumentException("UTrie2 serialized format error.");143}144145Trie2 This;146This = new Trie2_16();147This.header = header;148149/* get the length values and offsets */150This.indexLength = header.indexLength;151This.dataLength = header.shiftedDataLength << UTRIE2_INDEX_SHIFT;152This.index2NullOffset = header.index2NullOffset;153This.dataNullOffset = header.dataNullOffset;154This.highStart = header.shiftedHighStart << UTRIE2_SHIFT_1;155This.highValueIndex = This.dataLength - UTRIE2_DATA_GRANULARITY;156This.highValueIndex += This.indexLength;157158// Allocate the Trie2 index array. If the data width is 16 bits, the array also159// includes the space for the data.160161int indexArraySize = This.indexLength;162indexArraySize += This.dataLength;163This.index = new char[indexArraySize];164165/* Read in the index */166int i;167for (i=0; i<This.indexLength; i++) {168This.index[i] = bytes.getChar();169}170171/* Read in the data. 16 bit data goes in the same array as the index.172* 32 bit data goes in its own separate data array.173*/174This.data16 = This.indexLength;175for (i=0; i<This.dataLength; i++) {176This.index[This.data16 + i] = bytes.getChar();177}178179This.data32 = null;180This.initialValue = This.index[This.dataNullOffset];181This.errorValue = This.index[This.data16+UTRIE2_BAD_UTF8_DATA_OFFSET];182183return This;184} finally {185bytes.order(outerByteOrder);186}187}188189/**190* Get the value for a code point as stored in the Trie2.191*192* @param codePoint the code point193* @return the value194*/195public abstract int get(int codePoint);196197/**198* Get the trie value for a UTF-16 code unit.199*200* A Trie2 stores two distinct values for input in the lead surrogate201* range, one for lead surrogates, which is the value that will be202* returned by this function, and a second value that is returned203* by Trie2.get().204*205* For code units outside of the lead surrogate range, this function206* returns the same result as Trie2.get().207*208* This function, together with the alternate value for lead surrogates,209* makes possible very efficient processing of UTF-16 strings without210* first converting surrogate pairs to their corresponding 32 bit code point211* values.212*213* At build-time, enumerate the contents of the Trie2 to see if there214* is non-trivial (non-initialValue) data for any of the supplementary215* code points associated with a lead surrogate.216* If so, then set a special (application-specific) value for the217* lead surrogate code _unit_, with Trie2Writable.setForLeadSurrogateCodeUnit().218*219* At runtime, use Trie2.getFromU16SingleLead(). If there is non-trivial220* data and the code unit is a lead surrogate, then check if a trail surrogate221* follows. If so, assemble the supplementary code point and look up its value222* with Trie2.get(); otherwise reset the lead223* surrogate's value or do a code point lookup for it.224*225* If there is only trivial data for lead and trail surrogates, then processing226* can often skip them. For example, in normalization or case mapping227* all characters that do not have any mappings are simply copied as is.228*229* @param c the code point or lead surrogate value.230* @return the value231*/232public abstract int getFromU16SingleLead(char c);233234/**235* When iterating over the contents of a Trie2, Elements of this type are produced.236* The iterator will return one item for each contiguous range of codepoints having the same value.237*238* When iterating, the same Trie2EnumRange object will be reused and returned for each range.239* If you need to retain complete iteration results, clone each returned Trie2EnumRange,240* or save the range in some other way, before advancing to the next iteration step.241*/242public static class Range {243public int startCodePoint;244public int endCodePoint; // Inclusive.245public int value;246public boolean leadSurrogate;247248public boolean equals(Object other) {249if (other == null || !(other.getClass().equals(getClass()))) {250return false;251}252Range tother = (Range)other;253return this.startCodePoint == tother.startCodePoint &&254this.endCodePoint == tother.endCodePoint &&255this.value == tother.value &&256this.leadSurrogate == tother.leadSurrogate;257}258259public int hashCode() {260int h = initHash();261h = hashUChar32(h, startCodePoint);262h = hashUChar32(h, endCodePoint);263h = hashInt(h, value);264h = hashByte(h, leadSurrogate? 1: 0);265return h;266}267}268269/**270* Create an iterator over the value ranges in this Trie2.271* Values from the Trie2 are not remapped or filtered, but are returned as they272* are stored in the Trie2.273*274* @return an Iterator275*/276public Iterator<Range> iterator() {277return iterator(defaultValueMapper);278}279280private static ValueMapper defaultValueMapper = new ValueMapper() {281public int map(int in) {282return in;283}284};285286/**287* Create an iterator over the value ranges from this Trie2.288* Values from the Trie2 are passed through a caller-supplied remapping function,289* and it is the remapped values that determine the ranges that290* will be produced by the iterator.291*292*293* @param mapper provides a function to remap values obtained from the Trie2.294* @return an Iterator295*/296public Iterator<Range> iterator(ValueMapper mapper) {297return new Trie2Iterator(mapper);298}299300/**301* When iterating over the contents of a Trie2, an instance of TrieValueMapper may302* be used to remap the values from the Trie2. The remapped values will be used303* both in determining the ranges of codepoints and as the value to be returned304* for each range.305*306* Example of use, with an anonymous subclass of TrieValueMapper:307*308*309* ValueMapper m = new ValueMapper() {310* int map(int in) {return in & 0x1f;};311* }312* for (Iterator<Trie2EnumRange> iter = trie.iterator(m); i.hasNext(); ) {313* Trie2EnumRange r = i.next();314* ... // Do something with the range r.315* }316*317*/318public interface ValueMapper {319public int map(int originalVal);320}321322//--------------------------------------------------------------------------------323//324// Below this point are internal implementation items. No further public API.325//326//--------------------------------------------------------------------------------327328/**329* Trie2 data structure in serialized form:330*331* UTrie2Header header;332* uint16_t index[header.index2Length];333* uint16_t data[header.shiftedDataLength<<2]; -- or uint32_t data[...]334*335* For Java, this is read from the stream into an instance of UTrie2Header.336* (The C version just places a struct over the raw serialized data.)337*338* @internal339*/340static class UTrie2Header {341/** "Tri2" in big-endian US-ASCII (0x54726932) */342int signature;343344/**345* options bit field (uint16_t):346* 15.. 4 reserved (0)347* 3.. 0 UTrie2ValueBits valueBits348*/349int options;350351/** UTRIE2_INDEX_1_OFFSET..UTRIE2_MAX_INDEX_LENGTH (uint16_t) */352int indexLength;353354/** (UTRIE2_DATA_START_OFFSET..UTRIE2_MAX_DATA_LENGTH)>>UTRIE2_INDEX_SHIFT (uint16_t) */355int shiftedDataLength;356357/** Null index and data blocks, not shifted. (uint16_t) */358int index2NullOffset, dataNullOffset;359360/**361* First code point of the single-value range ending with U+10ffff,362* rounded up and then shifted right by UTRIE2_SHIFT_1. (uint16_t)363*/364int shiftedHighStart;365}366367//368// Data members of UTrie2.369//370UTrie2Header header;371char index[]; // Index array. Includes data for 16 bit Tries.372int data16; // Offset to data portion of the index array, if 16 bit data.373// zero if 32 bit data.374int data32[]; // NULL if 16b data is used via index375376int indexLength;377int dataLength;378int index2NullOffset; // 0xffff if there is no dedicated index-2 null block379int initialValue;380381/** Value returned for out-of-range code points and illegal UTF-8. */382int errorValue;383384/* Start of the last range which ends at U+10ffff, and its value. */385int highStart;386int highValueIndex;387388int dataNullOffset;389390/**391* Trie2 constants, defining shift widths, index array lengths, etc.392*393* These are needed for the runtime macros but users can treat these as394* implementation details and skip to the actual public API further below.395*/396397static final int UTRIE2_OPTIONS_VALUE_BITS_MASK=0x000f;398399400/** Shift size for getting the index-1 table offset. */401static final int UTRIE2_SHIFT_1=6+5;402403/** Shift size for getting the index-2 table offset. */404static final int UTRIE2_SHIFT_2=5;405406/**407* Difference between the two shift sizes,408* for getting an index-1 offset from an index-2 offset. 6=11-5409*/410static final int UTRIE2_SHIFT_1_2=UTRIE2_SHIFT_1-UTRIE2_SHIFT_2;411412/**413* Number of index-1 entries for the BMP. 32=0x20414* This part of the index-1 table is omitted from the serialized form.415*/416static final int UTRIE2_OMITTED_BMP_INDEX_1_LENGTH=0x10000>>UTRIE2_SHIFT_1;417418/** Number of entries in an index-2 block. 64=0x40 */419static final int UTRIE2_INDEX_2_BLOCK_LENGTH=1<<UTRIE2_SHIFT_1_2;420421/** Mask for getting the lower bits for the in-index-2-block offset. */422static final int UTRIE2_INDEX_2_MASK=UTRIE2_INDEX_2_BLOCK_LENGTH-1;423424/** Number of entries in a data block. 32=0x20 */425static final int UTRIE2_DATA_BLOCK_LENGTH=1<<UTRIE2_SHIFT_2;426427/** Mask for getting the lower bits for the in-data-block offset. */428static final int UTRIE2_DATA_MASK=UTRIE2_DATA_BLOCK_LENGTH-1;429430/**431* Shift size for shifting left the index array values.432* Increases possible data size with 16-bit index values at the cost433* of compactability.434* This requires data blocks to be aligned by UTRIE2_DATA_GRANULARITY.435*/436static final int UTRIE2_INDEX_SHIFT=2;437438/** The alignment size of a data block. Also the granularity for compaction. */439static final int UTRIE2_DATA_GRANULARITY=1<<UTRIE2_INDEX_SHIFT;440441/**442* The part of the index-2 table for U+D800..U+DBFF stores values for443* lead surrogate code _units_ not code _points_.444* Values for lead surrogate code _points_ are indexed with this portion of the table.445* Length=32=0x20=0x400>>UTRIE2_SHIFT_2. (There are 1024=0x400 lead surrogates.)446*/447static final int UTRIE2_LSCP_INDEX_2_OFFSET=0x10000>>UTRIE2_SHIFT_2;448static final int UTRIE2_LSCP_INDEX_2_LENGTH=0x400>>UTRIE2_SHIFT_2;449450/** Count the lengths of both BMP pieces. 2080=0x820 */451static final int UTRIE2_INDEX_2_BMP_LENGTH=UTRIE2_LSCP_INDEX_2_OFFSET+UTRIE2_LSCP_INDEX_2_LENGTH;452453/**454* The 2-byte UTF-8 version of the index-2 table follows at offset 2080=0x820.455* Length 32=0x20 for lead bytes C0..DF, regardless of UTRIE2_SHIFT_2.456*/457static final int UTRIE2_UTF8_2B_INDEX_2_OFFSET=UTRIE2_INDEX_2_BMP_LENGTH;458static final int UTRIE2_UTF8_2B_INDEX_2_LENGTH=0x800>>6; /* U+0800 is the first code point after 2-byte UTF-8 */459460/**461* The index-1 table, only used for supplementary code points, at offset 2112=0x840.462* Variable length, for code points up to highStart, where the last single-value range starts.463* Maximum length 512=0x200=0x100000>>UTRIE2_SHIFT_1.464* (For 0x100000 supplementary code points U+10000..U+10ffff.)465*466* The part of the index-2 table for supplementary code points starts467* after this index-1 table.468*469* Both the index-1 table and the following part of the index-2 table470* are omitted completely if there is only BMP data.471*/472static final int UTRIE2_INDEX_1_OFFSET=UTRIE2_UTF8_2B_INDEX_2_OFFSET+UTRIE2_UTF8_2B_INDEX_2_LENGTH;473474/**475* The illegal-UTF-8 data block follows the ASCII block, at offset 128=0x80.476* Used with linear access for single bytes 0..0xbf for simple error handling.477* Length 64=0x40, not UTRIE2_DATA_BLOCK_LENGTH.478*/479static final int UTRIE2_BAD_UTF8_DATA_OFFSET=0x80;480481/**482* Implementation class for an iterator over a Trie2.483*484* Iteration over a Trie2 first returns all of the ranges that are indexed by code points,485* then returns the special alternate values for the lead surrogates486*487* @internal488*/489class Trie2Iterator implements Iterator<Range> {490491// The normal constructor that configures the iterator to cover the complete492// contents of the Trie2493Trie2Iterator(ValueMapper vm) {494mapper = vm;495nextStart = 0;496limitCP = 0x110000;497doLeadSurrogates = true;498}499500/**501* The main next() function for Trie2 iterators502*503*/504public Range next() {505if (!hasNext()) {506throw new NoSuchElementException();507}508if (nextStart >= limitCP) {509// Switch over from iterating normal code point values to510// doing the alternate lead-surrogate values.511doingCodePoints = false;512nextStart = 0xd800;513}514int endOfRange = 0;515int val = 0;516int mappedVal = 0;517518if (doingCodePoints) {519// Iteration over code point values.520val = get(nextStart);521mappedVal = mapper.map(val);522endOfRange = rangeEnd(nextStart, limitCP, val);523// Loop once for each range in the Trie2 with the same raw (unmapped) value.524// Loop continues so long as the mapped values are the same.525for (;;) {526if (endOfRange >= limitCP-1) {527break;528}529val = get(endOfRange+1);530if (mapper.map(val) != mappedVal) {531break;532}533endOfRange = rangeEnd(endOfRange+1, limitCP, val);534}535} else {536// Iteration over the alternate lead surrogate values.537val = getFromU16SingleLead((char)nextStart);538mappedVal = mapper.map(val);539endOfRange = rangeEndLS((char)nextStart);540// Loop once for each range in the Trie2 with the same raw (unmapped) value.541// Loop continues so long as the mapped values are the same.542for (;;) {543if (endOfRange >= 0xdbff) {544break;545}546val = getFromU16SingleLead((char)(endOfRange+1));547if (mapper.map(val) != mappedVal) {548break;549}550endOfRange = rangeEndLS((char)(endOfRange+1));551}552}553returnValue.startCodePoint = nextStart;554returnValue.endCodePoint = endOfRange;555returnValue.value = mappedVal;556returnValue.leadSurrogate = !doingCodePoints;557nextStart = endOfRange+1;558return returnValue;559}560561/**562*563*/564public boolean hasNext() {565return doingCodePoints && (doLeadSurrogates || nextStart < limitCP) || nextStart < 0xdc00;566}567568private int rangeEndLS(char startingLS) {569if (startingLS >= 0xdbff) {570return 0xdbff;571}572573int c;574int val = getFromU16SingleLead(startingLS);575for (c = startingLS+1; c <= 0x0dbff; c++) {576if (getFromU16SingleLead((char)c) != val) {577break;578}579}580return c-1;581}582583//584// Iteration State Variables585//586private ValueMapper mapper;587private Range returnValue = new Range();588// The starting code point for the next range to be returned.589private int nextStart;590// The upper limit for the last normal range to be returned. Normally 0x110000, but591// may be lower when iterating over the code points for a single lead surrogate.592private int limitCP;593594// True while iterating over the Trie2 values for code points.595// False while iterating over the alternate values for lead surrogates.596private boolean doingCodePoints = true;597598// True if the iterator should iterate the special values for lead surrogates in599// addition to the normal values for code points.600private boolean doLeadSurrogates = true;601}602603/**604* Find the last character in a contiguous range of characters with the605* same Trie2 value as the input character.606*607* @param c The character to begin with.608* @return The last contiguous character with the same value.609*/610int rangeEnd(int start, int limitp, int val) {611int c;612int limit = Math.min(highStart, limitp);613614for (c = start+1; c < limit; c++) {615if (get(c) != val) {616break;617}618}619if (c >= highStart) {620c = limitp;621}622return c - 1;623}624625626//627// Hashing implementation functions. FNV hash. Respected public domain algorithm.628//629private static int initHash() {630return 0x811c9DC5; // unsigned 2166136261631}632633private static int hashByte(int h, int b) {634h = h * 16777619;635h = h ^ b;636return h;637}638639private static int hashUChar32(int h, int c) {640h = Trie2.hashByte(h, c & 255);641h = Trie2.hashByte(h, (c>>8) & 255);642h = Trie2.hashByte(h, c>>16);643return h;644}645646private static int hashInt(int h, int i) {647h = Trie2.hashByte(h, i & 255);648h = Trie2.hashByte(h, (i>>8) & 255);649h = Trie2.hashByte(h, (i>>16) & 255);650h = Trie2.hashByte(h, (i>>24) & 255);651return h;652}653654}655656657