1 /* GENERATED SOURCE. DO NOT MODIFY. */ 2 // © 2016 and later: Unicode, Inc. and others. 3 // License & terms of use: http://www.unicode.org/copyright.html#License 4 /* 5 ******************************************************************************* 6 * Copyright (C) 2009-2015, International Business Machines Corporation and 7 * others. All Rights Reserved. 8 ******************************************************************************* 9 */ 10 11 package ohos.global.icu.impl; 12 13 import java.io.DataOutputStream; 14 import java.io.IOException; 15 import java.io.InputStream; 16 import java.nio.ByteBuffer; 17 import java.nio.ByteOrder; 18 import java.util.Iterator; 19 import java.util.NoSuchElementException; 20 21 22 /** 23 * This is the interface and common implementation of a Unicode Trie2. 24 * It is a kind of compressed table that maps from Unicode code points (0..0x10ffff) 25 * to 16- or 32-bit integer values. It works best when there are ranges of 26 * characters with the same value, which is generally the case with Unicode 27 * character properties. 28 * 29 * This is the second common version of a Unicode trie (hence the name Trie2). 30 * @hide exposed on OHOS 31 * 32 */ 33 public abstract class Trie2 implements Iterable<Trie2.Range> { 34 35 36 /** 37 * Create a Trie2 from its serialized form. Inverse of utrie2_serialize(). 38 * 39 * Reads from the current position and leaves the buffer after the end of the trie. 40 * 41 * The serialized format is identical between ICU4C and ICU4J, so this function 42 * will work with serialized Trie2s from either. 43 * 44 * The actual type of the returned Trie2 will be either Trie2_16 or Trie2_32, depending 45 * on the width of the data. 46 * 47 * To obtain the width of the Trie2, check the actual class type of the returned Trie2. 48 * Or use the createFromSerialized() function of Trie2_16 or Trie2_32, which will 49 * return only Tries of their specific type/size. 50 * 51 * The serialized Trie2 on the stream may be in either little or big endian byte order. 52 * This allows using serialized Tries from ICU4C without needing to consider the 53 * byte order of the system that created them. 54 * 55 * @param bytes a byte buffer to the serialized form of a UTrie2. 56 * @return An unserialized Trie2, ready for use. 57 * @throws IllegalArgumentException if the stream does not contain a serialized Trie2. 58 * @throws IOException if a read error occurs in the buffer. 59 * 60 */ createFromSerialized(ByteBuffer bytes)61 public static Trie2 createFromSerialized(ByteBuffer bytes) throws IOException { 62 // From ICU4C utrie2_impl.h 63 // * Trie2 data structure in serialized form: 64 // * 65 // * UTrie2Header header; 66 // * uint16_t index[header.index2Length]; 67 // * uint16_t data[header.shiftedDataLength<<2]; -- or uint32_t data[...] 68 // * @internal 69 // */ 70 // typedef struct UTrie2Header { 71 // /** "Tri2" in big-endian US-ASCII (0x54726932) */ 72 // uint32_t signature; 73 74 // /** 75 // * options bit field: 76 // * 15.. 4 reserved (0) 77 // * 3.. 0 UTrie2ValueBits valueBits 78 // */ 79 // uint16_t options; 80 // 81 // /** UTRIE2_INDEX_1_OFFSET..UTRIE2_MAX_INDEX_LENGTH */ 82 // uint16_t indexLength; 83 // 84 // /** (UTRIE2_DATA_START_OFFSET..UTRIE2_MAX_DATA_LENGTH)>>UTRIE2_INDEX_SHIFT */ 85 // uint16_t shiftedDataLength; 86 // 87 // /** Null index and data blocks, not shifted. */ 88 // uint16_t index2NullOffset, dataNullOffset; 89 // 90 // /** 91 // * First code point of the single-value range ending with U+10ffff, 92 // * rounded up and then shifted right by UTRIE2_SHIFT_1. 93 // */ 94 // uint16_t shiftedHighStart; 95 // } UTrie2Header; 96 97 ByteOrder outerByteOrder = bytes.order(); 98 try { 99 UTrie2Header header = new UTrie2Header(); 100 101 /* check the signature */ 102 header.signature = bytes.getInt(); 103 switch (header.signature) { 104 case 0x54726932: 105 // The buffer is already set to the trie data byte order. 106 break; 107 case 0x32697254: 108 // Temporarily reverse the byte order. 109 boolean isBigEndian = outerByteOrder == ByteOrder.BIG_ENDIAN; 110 bytes.order(isBigEndian ? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN); 111 header.signature = 0x54726932; 112 break; 113 default: 114 throw new IllegalArgumentException("Buffer does not contain a serialized UTrie2"); 115 } 116 117 header.options = bytes.getChar(); 118 header.indexLength = bytes.getChar(); 119 header.shiftedDataLength = bytes.getChar(); 120 header.index2NullOffset = bytes.getChar(); 121 header.dataNullOffset = bytes.getChar(); 122 header.shiftedHighStart = bytes.getChar(); 123 124 // Trie2 data width - 0: 16 bits 125 // 1: 32 bits 126 if ((header.options & UTRIE2_OPTIONS_VALUE_BITS_MASK) > 1) { 127 throw new IllegalArgumentException("UTrie2 serialized format error."); 128 } 129 ValueWidth width; 130 Trie2 This; 131 if ((header.options & UTRIE2_OPTIONS_VALUE_BITS_MASK) == 0) { 132 width = ValueWidth.BITS_16; 133 This = new Trie2_16(); 134 } else { 135 width = ValueWidth.BITS_32; 136 This = new Trie2_32(); 137 } 138 This.header = header; 139 140 /* get the length values and offsets */ 141 This.indexLength = header.indexLength; 142 This.dataLength = header.shiftedDataLength << UTRIE2_INDEX_SHIFT; 143 This.index2NullOffset = header.index2NullOffset; 144 This.dataNullOffset = header.dataNullOffset; 145 This.highStart = header.shiftedHighStart << UTRIE2_SHIFT_1; 146 This.highValueIndex = This.dataLength - UTRIE2_DATA_GRANULARITY; 147 if (width == ValueWidth.BITS_16) { 148 This.highValueIndex += This.indexLength; 149 } 150 151 // Allocate the Trie2 index array. If the data width is 16 bits, the array also 152 // includes the space for the data. 153 154 int indexArraySize = This.indexLength; 155 if (width == ValueWidth.BITS_16) { 156 indexArraySize += This.dataLength; 157 } 158 159 /* Read in the index */ 160 This.index = ICUBinary.getChars(bytes, indexArraySize, 0); 161 162 /* Read in the data. 16 bit data goes in the same array as the index. 163 * 32 bit data goes in its own separate data array. 164 */ 165 if (width == ValueWidth.BITS_16) { 166 This.data16 = This.indexLength; 167 } else { 168 This.data32 = ICUBinary.getInts(bytes, This.dataLength, 0); 169 } 170 171 switch(width) { 172 case BITS_16: 173 This.data32 = null; 174 This.initialValue = This.index[This.dataNullOffset]; 175 This.errorValue = This.index[This.data16+UTRIE2_BAD_UTF8_DATA_OFFSET]; 176 break; 177 case BITS_32: 178 This.data16=0; 179 This.initialValue = This.data32[This.dataNullOffset]; 180 This.errorValue = This.data32[UTRIE2_BAD_UTF8_DATA_OFFSET]; 181 break; 182 default: 183 throw new IllegalArgumentException("UTrie2 serialized format error."); 184 } 185 186 return This; 187 } finally { 188 bytes.order(outerByteOrder); 189 } 190 } 191 192 /** 193 * Get the UTrie version from an InputStream containing the serialized form 194 * of either a Trie (version 1) or a Trie2 (version 2). 195 * 196 * @param is an InputStream containing the serialized form 197 * of a UTrie, version 1 or 2. The stream must support mark() and reset(). 198 * The position of the input stream will be left unchanged. 199 * @param littleEndianOk If FALSE, only big-endian (Java native) serialized forms are recognized. 200 * If TRUE, little-endian serialized forms are recognized as well. 201 * @return the Trie version of the serialized form, or 0 if it is not 202 * recognized as a serialized UTrie 203 * @throws IOException on errors in reading from the input stream. 204 */ getVersion(InputStream is, boolean littleEndianOk)205 public static int getVersion(InputStream is, boolean littleEndianOk) throws IOException { 206 if (! is.markSupported()) { 207 throw new IllegalArgumentException("Input stream must support mark()."); 208 } 209 is.mark(4); 210 byte sig[] = new byte[4]; 211 int read = is.read(sig); 212 is.reset(); 213 214 if (read != sig.length) { 215 return 0; 216 } 217 218 if (sig[0]=='T' && sig[1]=='r' && sig[2]=='i' && sig[3]=='e') { 219 return 1; 220 } 221 if (sig[0]=='T' && sig[1]=='r' && sig[2]=='i' && sig[3]=='2') { 222 return 2; 223 } 224 if (littleEndianOk) { 225 if (sig[0]=='e' && sig[1]=='i' && sig[2]=='r' && sig[3]=='T') { 226 return 1; 227 } 228 if (sig[0]=='2' && sig[1]=='i' && sig[2]=='r' && sig[3]=='T') { 229 return 2; 230 } 231 } 232 return 0; 233 } 234 235 /** 236 * Get the value for a code point as stored in the Trie2. 237 * 238 * @param codePoint the code point 239 * @return the value 240 */ get(int codePoint)241 abstract public int get(int codePoint); 242 243 244 /** 245 * Get the trie value for a UTF-16 code unit. 246 * 247 * A Trie2 stores two distinct values for input in the lead surrogate 248 * range, one for lead surrogates, which is the value that will be 249 * returned by this function, and a second value that is returned 250 * by Trie2.get(). 251 * 252 * For code units outside of the lead surrogate range, this function 253 * returns the same result as Trie2.get(). 254 * 255 * This function, together with the alternate value for lead surrogates, 256 * makes possible very efficient processing of UTF-16 strings without 257 * first converting surrogate pairs to their corresponding 32 bit code point 258 * values. 259 * 260 * At build-time, enumerate the contents of the Trie2 to see if there 261 * is non-trivial (non-initialValue) data for any of the supplementary 262 * code points associated with a lead surrogate. 263 * If so, then set a special (application-specific) value for the 264 * lead surrogate code _unit_, with Trie2Writable.setForLeadSurrogateCodeUnit(). 265 * 266 * At runtime, use Trie2.getFromU16SingleLead(). If there is non-trivial 267 * data and the code unit is a lead surrogate, then check if a trail surrogate 268 * follows. If so, assemble the supplementary code point and look up its value 269 * with Trie2.get(); otherwise reset the lead 270 * surrogate's value or do a code point lookup for it. 271 * 272 * If there is only trivial data for lead and trail surrogates, then processing 273 * can often skip them. For example, in normalization or case mapping 274 * all characters that do not have any mappings are simply copied as is. 275 * 276 * @param c the code point or lead surrogate value. 277 * @return the value 278 */ getFromU16SingleLead(char c)279 abstract public int getFromU16SingleLead(char c); 280 281 282 /** 283 * Equals function. Two Tries are equal if their contents are equal. 284 * The type need not be the same, so a Trie2Writable will be equal to 285 * (read-only) Trie2_16 or Trie2_32 so long as they are storing the same values. 286 * 287 */ 288 @Override equals(Object other)289 public final boolean equals(Object other) { 290 if(!(other instanceof Trie2)) { 291 return false; 292 } 293 Trie2 OtherTrie = (Trie2)other; 294 Range rangeFromOther; 295 296 Iterator<Trie2.Range> otherIter = OtherTrie.iterator(); 297 for (Trie2.Range rangeFromThis: this) { 298 if (otherIter.hasNext() == false) { 299 return false; 300 } 301 rangeFromOther = otherIter.next(); 302 if (!rangeFromThis.equals(rangeFromOther)) { 303 return false; 304 } 305 } 306 if (otherIter.hasNext()) { 307 return false; 308 } 309 310 if (errorValue != OtherTrie.errorValue || 311 initialValue != OtherTrie.initialValue) { 312 return false; 313 } 314 315 return true; 316 } 317 318 319 @Override hashCode()320 public int hashCode() { 321 if (fHash == 0) { 322 int hash = initHash(); 323 for (Range r: this) { 324 hash = hashInt(hash, r.hashCode()); 325 } 326 if (hash == 0) { 327 hash = 1; 328 } 329 fHash = hash; 330 } 331 return fHash; 332 } 333 334 /** 335 * When iterating over the contents of a Trie2, Elements of this type are produced. 336 * The iterator will return one item for each contiguous range of codepoints having the same value. 337 * 338 * When iterating, the same Trie2EnumRange object will be reused and returned for each range. 339 * If you need to retain complete iteration results, clone each returned Trie2EnumRange, 340 * or save the range in some other way, before advancing to the next iteration step. 341 * @hide exposed on OHOS 342 */ 343 public static class Range { 344 public int startCodePoint; 345 public int endCodePoint; // Inclusive. 346 public int value; 347 public boolean leadSurrogate; 348 349 @Override equals(Object other)350 public boolean equals(Object other) { 351 if (other == null || !(other.getClass().equals(getClass()))) { 352 return false; 353 } 354 Range tother = (Range)other; 355 return this.startCodePoint == tother.startCodePoint && 356 this.endCodePoint == tother.endCodePoint && 357 this.value == tother.value && 358 this.leadSurrogate == tother.leadSurrogate; 359 } 360 361 362 @Override hashCode()363 public int hashCode() { 364 int h = initHash(); 365 h = hashUChar32(h, startCodePoint); 366 h = hashUChar32(h, endCodePoint); 367 h = hashInt(h, value); 368 h = hashByte(h, leadSurrogate? 1: 0); 369 return h; 370 } 371 } 372 373 374 /** 375 * Create an iterator over the value ranges in this Trie2. 376 * Values from the Trie2 are not remapped or filtered, but are returned as they 377 * are stored in the Trie2. 378 * 379 * @return an Iterator 380 */ 381 @Override iterator()382 public Iterator<Range> iterator() { 383 return iterator(defaultValueMapper); 384 } 385 386 private static ValueMapper defaultValueMapper = new ValueMapper() { 387 @Override 388 public int map(int in) { 389 return in; 390 } 391 }; 392 393 /** 394 * Create an iterator over the value ranges from this Trie2. 395 * Values from the Trie2 are passed through a caller-supplied remapping function, 396 * and it is the remapped values that determine the ranges that 397 * will be produced by the iterator. 398 * 399 * 400 * @param mapper provides a function to remap values obtained from the Trie2. 401 * @return an Iterator 402 */ iterator(ValueMapper mapper)403 public Iterator<Range> iterator(ValueMapper mapper) { 404 return new Trie2Iterator(mapper); 405 } 406 407 408 /** 409 * Create an iterator over the Trie2 values for the 1024=0x400 code points 410 * corresponding to a given lead surrogate. 411 * For example, for the lead surrogate U+D87E it will enumerate the values 412 * for [U+2F800..U+2FC00[. 413 * Used by data builder code that sets special lead surrogate code unit values 414 * for optimized UTF-16 string processing. 415 * 416 * Do not modify the Trie2 during the iteration. 417 * 418 * Except for the limited code point range, this functions just like Trie2.iterator(). 419 * 420 */ iteratorForLeadSurrogate(char lead, ValueMapper mapper)421 public Iterator<Range> iteratorForLeadSurrogate(char lead, ValueMapper mapper) { 422 return new Trie2Iterator(lead, mapper); 423 } 424 425 /** 426 * Create an iterator over the Trie2 values for the 1024=0x400 code points 427 * corresponding to a given lead surrogate. 428 * For example, for the lead surrogate U+D87E it will enumerate the values 429 * for [U+2F800..U+2FC00[. 430 * Used by data builder code that sets special lead surrogate code unit values 431 * for optimized UTF-16 string processing. 432 * 433 * Do not modify the Trie2 during the iteration. 434 * 435 * Except for the limited code point range, this functions just like Trie2.iterator(). 436 * 437 */ iteratorForLeadSurrogate(char lead)438 public Iterator<Range> iteratorForLeadSurrogate(char lead) { 439 return new Trie2Iterator(lead, defaultValueMapper); 440 } 441 442 /** 443 * When iterating over the contents of a Trie2, an instance of TrieValueMapper may 444 * be used to remap the values from the Trie2. The remapped values will be used 445 * both in determining the ranges of codepoints and as the value to be returned 446 * for each range. 447 * 448 * Example of use, with an anonymous subclass of TrieValueMapper: 449 * 450 * 451 * ValueMapper m = new ValueMapper() { 452 * int map(int in) {return in & 0x1f;}; 453 * } 454 * for (Iterator<Trie2EnumRange> iter = trie.iterator(m); i.hasNext(); ) { 455 * Trie2EnumRange r = i.next(); 456 * ... // Do something with the range r. 457 * } 458 * @hide exposed on OHOS 459 * 460 */ 461 public interface ValueMapper { map(int originalVal)462 public int map(int originalVal); 463 } 464 465 466 /** 467 * Serialize a trie2 Header and Index onto an OutputStream. This is 468 * common code used for both the Trie2_16 and Trie2_32 serialize functions. 469 * @param dos the stream to which the serialized Trie2 data will be written. 470 * @return the number of bytes written. 471 */ serializeHeader(DataOutputStream dos)472 protected int serializeHeader(DataOutputStream dos) throws IOException { 473 // Write the header. It is already set and ready to use, having been 474 // created when the Trie2 was unserialized or when it was frozen. 475 int bytesWritten = 0; 476 477 dos.writeInt(header.signature); 478 dos.writeShort(header.options); 479 dos.writeShort(header.indexLength); 480 dos.writeShort(header.shiftedDataLength); 481 dos.writeShort(header.index2NullOffset); 482 dos.writeShort(header.dataNullOffset); 483 dos.writeShort(header.shiftedHighStart); 484 bytesWritten += 16; 485 486 // Write the index 487 int i; 488 for (i=0; i< header.indexLength; i++) { 489 dos.writeChar(index[i]); 490 } 491 bytesWritten += header.indexLength; 492 return bytesWritten; 493 } 494 495 496 /** 497 * Struct-like class for holding the results returned by a UTrie2 CharSequence iterator. 498 * The iteration walks over a CharSequence, and for each Unicode code point therein 499 * returns the character and its associated Trie2 value. 500 * @hide exposed on OHOS 501 */ 502 public static class CharSequenceValues { 503 /** string index of the current code point. */ 504 public int index; 505 /** The code point at index. */ 506 public int codePoint; 507 /** The Trie2 value for the current code point */ 508 public int value; 509 } 510 511 512 /** 513 * Create an iterator that will produce the values from the Trie2 for 514 * the sequence of code points in an input text. 515 * 516 * @param text A text string to be iterated over. 517 * @param index The starting iteration position within the input text. 518 * @return the CharSequenceIterator 519 */ charSequenceIterator(CharSequence text, int index)520 public CharSequenceIterator charSequenceIterator(CharSequence text, int index) { 521 return new CharSequenceIterator(text, index); 522 } 523 524 // TODO: Survey usage of the equivalent of CharSequenceIterator in ICU4C 525 // and if there is none, remove it from here. 526 // Don't waste time testing and maintaining unused code. 527 528 /** 529 * An iterator that operates over an input CharSequence, and for each Unicode code point 530 * in the input returns the associated value from the Trie2. 531 * 532 * The iterator can move forwards or backwards, and can be reset to an arbitrary index. 533 * 534 * Note that Trie2_16 and Trie2_32 subclass Trie2.CharSequenceIterator. This is done 535 * only for performance reasons. It does require that any changes made here be propagated 536 * into the corresponding code in the subclasses. 537 * @hide exposed on OHOS 538 */ 539 public class CharSequenceIterator implements Iterator<CharSequenceValues> { 540 /** 541 * Internal constructor. 542 */ CharSequenceIterator(CharSequence t, int index)543 CharSequenceIterator(CharSequence t, int index) { 544 text = t; 545 textLength = text.length(); 546 set(index); 547 } 548 549 private CharSequence text; 550 private int textLength; 551 private int index; 552 private Trie2.CharSequenceValues fResults = new Trie2.CharSequenceValues(); 553 554 set(int i)555 public void set(int i) { 556 if (i < 0 || i > textLength) { 557 throw new IndexOutOfBoundsException(); 558 } 559 index = i; 560 } 561 562 563 @Override hasNext()564 public final boolean hasNext() { 565 return index<textLength; 566 } 567 568 hasPrevious()569 public final boolean hasPrevious() { 570 return index>0; 571 } 572 573 574 @Override next()575 public Trie2.CharSequenceValues next() { 576 int c = Character.codePointAt(text, index); 577 int val = get(c); 578 579 fResults.index = index; 580 fResults.codePoint = c; 581 fResults.value = val; 582 index++; 583 if (c >= 0x10000) { 584 index++; 585 } 586 return fResults; 587 } 588 589 previous()590 public Trie2.CharSequenceValues previous() { 591 int c = Character.codePointBefore(text, index); 592 int val = get(c); 593 index--; 594 if (c >= 0x10000) { 595 index--; 596 } 597 fResults.index = index; 598 fResults.codePoint = c; 599 fResults.value = val; 600 return fResults; 601 } 602 603 /** 604 * Iterator.remove() is not supported by Trie2.CharSequenceIterator. 605 * @throws UnsupportedOperationException Always thrown because this operation is not supported 606 * @see java.util.Iterator#remove() 607 */ 608 @Override remove()609 public void remove() { 610 throw new UnsupportedOperationException("Trie2.CharSequenceIterator does not support remove()."); 611 } 612 } 613 614 615 //-------------------------------------------------------------------------------- 616 // 617 // Below this point are internal implementation items. No further public API. 618 // 619 //-------------------------------------------------------------------------------- 620 621 622 /** 623 * Selectors for the width of a UTrie2 data value. 624 */ 625 enum ValueWidth { 626 BITS_16, 627 BITS_32 628 } 629 630 /** 631 * Trie2 data structure in serialized form: 632 * 633 * UTrie2Header header; 634 * uint16_t index[header.index2Length]; 635 * uint16_t data[header.shiftedDataLength<<2]; -- or uint32_t data[...] 636 * 637 * For Java, this is read from the stream into an instance of UTrie2Header. 638 * (The C version just places a struct over the raw serialized data.) 639 * 640 * @hide draft / provisional / internal are hidden on OHOS 641 */ 642 static class UTrie2Header { 643 /** "Tri2" in big-endian US-ASCII (0x54726932) */ 644 int signature; 645 646 /** 647 * options bit field (uint16_t): 648 * 15.. 4 reserved (0) 649 * 3.. 0 UTrie2ValueBits valueBits 650 */ 651 int options; 652 653 /** UTRIE2_INDEX_1_OFFSET..UTRIE2_MAX_INDEX_LENGTH (uint16_t) */ 654 int indexLength; 655 656 /** (UTRIE2_DATA_START_OFFSET..UTRIE2_MAX_DATA_LENGTH)>>UTRIE2_INDEX_SHIFT (uint16_t) */ 657 int shiftedDataLength; 658 659 /** Null index and data blocks, not shifted. (uint16_t) */ 660 int index2NullOffset, dataNullOffset; 661 662 /** 663 * First code point of the single-value range ending with U+10ffff, 664 * rounded up and then shifted right by UTRIE2_SHIFT_1. (uint16_t) 665 */ 666 int shiftedHighStart; 667 } 668 669 // 670 // Data members of UTrie2. 671 // 672 UTrie2Header header; 673 char index[]; // Index array. Includes data for 16 bit Tries. 674 int data16; // Offset to data portion of the index array, if 16 bit data. 675 // zero if 32 bit data. 676 int data32[]; // NULL if 16b data is used via index 677 678 int indexLength; 679 int dataLength; 680 int index2NullOffset; // 0xffff if there is no dedicated index-2 null block 681 int initialValue; 682 683 /** Value returned for out-of-range code points and illegal UTF-8. */ 684 int errorValue; 685 686 /* Start of the last range which ends at U+10ffff, and its value. */ 687 int highStart; 688 int highValueIndex; 689 690 int dataNullOffset; 691 692 int fHash; // Zero if not yet computed. 693 // Shared by Trie2Writable, Trie2_16, Trie2_32. 694 // Thread safety: if two racing threads compute 695 // the same hash on a frozen Trie2, no damage is done. 696 697 698 /** 699 * Trie2 constants, defining shift widths, index array lengths, etc. 700 * 701 * These are needed for the runtime macros but users can treat these as 702 * implementation details and skip to the actual public API further below. 703 */ 704 705 static final int UTRIE2_OPTIONS_VALUE_BITS_MASK=0x000f; 706 707 708 /** Shift size for getting the index-1 table offset. */ 709 static final int UTRIE2_SHIFT_1=6+5; 710 711 /** Shift size for getting the index-2 table offset. */ 712 static final int UTRIE2_SHIFT_2=5; 713 714 /** 715 * Difference between the two shift sizes, 716 * for getting an index-1 offset from an index-2 offset. 6=11-5 717 */ 718 static final int UTRIE2_SHIFT_1_2=UTRIE2_SHIFT_1-UTRIE2_SHIFT_2; 719 720 /** 721 * Number of index-1 entries for the BMP. 32=0x20 722 * This part of the index-1 table is omitted from the serialized form. 723 */ 724 static final int UTRIE2_OMITTED_BMP_INDEX_1_LENGTH=0x10000>>UTRIE2_SHIFT_1; 725 726 /** Number of code points per index-1 table entry. 2048=0x800 */ 727 static final int UTRIE2_CP_PER_INDEX_1_ENTRY=1<<UTRIE2_SHIFT_1; 728 729 /** Number of entries in an index-2 block. 64=0x40 */ 730 static final int UTRIE2_INDEX_2_BLOCK_LENGTH=1<<UTRIE2_SHIFT_1_2; 731 732 /** Mask for getting the lower bits for the in-index-2-block offset. */ 733 static final int UTRIE2_INDEX_2_MASK=UTRIE2_INDEX_2_BLOCK_LENGTH-1; 734 735 /** Number of entries in a data block. 32=0x20 */ 736 static final int UTRIE2_DATA_BLOCK_LENGTH=1<<UTRIE2_SHIFT_2; 737 738 /** Mask for getting the lower bits for the in-data-block offset. */ 739 static final int UTRIE2_DATA_MASK=UTRIE2_DATA_BLOCK_LENGTH-1; 740 741 /** 742 * Shift size for shifting left the index array values. 743 * Increases possible data size with 16-bit index values at the cost 744 * of compactability. 745 * This requires data blocks to be aligned by UTRIE2_DATA_GRANULARITY. 746 */ 747 static final int UTRIE2_INDEX_SHIFT=2; 748 749 /** The alignment size of a data block. Also the granularity for compaction. */ 750 static final int UTRIE2_DATA_GRANULARITY=1<<UTRIE2_INDEX_SHIFT; 751 752 /* Fixed layout of the first part of the index array. ------------------- */ 753 754 /** 755 * The BMP part of the index-2 table is fixed and linear and starts at offset 0. 756 * Length=2048=0x800=0x10000>>UTRIE2_SHIFT_2. 757 */ 758 static final int UTRIE2_INDEX_2_OFFSET=0; 759 760 /** 761 * The part of the index-2 table for U+D800..U+DBFF stores values for 762 * lead surrogate code _units_ not code _points_. 763 * Values for lead surrogate code _points_ are indexed with this portion of the table. 764 * Length=32=0x20=0x400>>UTRIE2_SHIFT_2. (There are 1024=0x400 lead surrogates.) 765 */ 766 static final int UTRIE2_LSCP_INDEX_2_OFFSET=0x10000>>UTRIE2_SHIFT_2; 767 static final int UTRIE2_LSCP_INDEX_2_LENGTH=0x400>>UTRIE2_SHIFT_2; 768 769 /** Count the lengths of both BMP pieces. 2080=0x820 */ 770 static final int UTRIE2_INDEX_2_BMP_LENGTH=UTRIE2_LSCP_INDEX_2_OFFSET+UTRIE2_LSCP_INDEX_2_LENGTH; 771 772 /** 773 * The 2-byte UTF-8 version of the index-2 table follows at offset 2080=0x820. 774 * Length 32=0x20 for lead bytes C0..DF, regardless of UTRIE2_SHIFT_2. 775 */ 776 static final int UTRIE2_UTF8_2B_INDEX_2_OFFSET=UTRIE2_INDEX_2_BMP_LENGTH; 777 static final int UTRIE2_UTF8_2B_INDEX_2_LENGTH=0x800>>6; /* U+0800 is the first code point after 2-byte UTF-8 */ 778 779 /** 780 * The index-1 table, only used for supplementary code points, at offset 2112=0x840. 781 * Variable length, for code points up to highStart, where the last single-value range starts. 782 * Maximum length 512=0x200=0x100000>>UTRIE2_SHIFT_1. 783 * (For 0x100000 supplementary code points U+10000..U+10ffff.) 784 * 785 * The part of the index-2 table for supplementary code points starts 786 * after this index-1 table. 787 * 788 * Both the index-1 table and the following part of the index-2 table 789 * are omitted completely if there is only BMP data. 790 */ 791 static final int UTRIE2_INDEX_1_OFFSET=UTRIE2_UTF8_2B_INDEX_2_OFFSET+UTRIE2_UTF8_2B_INDEX_2_LENGTH; 792 static final int UTRIE2_MAX_INDEX_1_LENGTH=0x100000>>UTRIE2_SHIFT_1; 793 794 /* 795 * Fixed layout of the first part of the data array. ----------------------- 796 * Starts with 4 blocks (128=0x80 entries) for ASCII. 797 */ 798 799 /** 800 * The illegal-UTF-8 data block follows the ASCII block, at offset 128=0x80. 801 * Used with linear access for single bytes 0..0xbf for simple error handling. 802 * Length 64=0x40, not UTRIE2_DATA_BLOCK_LENGTH. 803 */ 804 static final int UTRIE2_BAD_UTF8_DATA_OFFSET=0x80; 805 806 /** The start of non-linear-ASCII data blocks, at offset 192=0xc0. */ 807 static final int UTRIE2_DATA_START_OFFSET=0xc0; 808 809 /* Building a Trie2 ---------------------------------------------------------- */ 810 811 /* 812 * These definitions are mostly needed by utrie2_builder.c, but also by 813 * utrie2_get32() and utrie2_enum(). 814 */ 815 816 /* 817 * At build time, leave a gap in the index-2 table, 818 * at least as long as the maximum lengths of the 2-byte UTF-8 index-2 table 819 * and the supplementary index-1 table. 820 * Round up to UTRIE2_INDEX_2_BLOCK_LENGTH for proper compacting. 821 */ 822 static final int UNEWTRIE2_INDEX_GAP_OFFSET = UTRIE2_INDEX_2_BMP_LENGTH; 823 static final int UNEWTRIE2_INDEX_GAP_LENGTH = 824 ((UTRIE2_UTF8_2B_INDEX_2_LENGTH + UTRIE2_MAX_INDEX_1_LENGTH) + UTRIE2_INDEX_2_MASK) & 825 ~UTRIE2_INDEX_2_MASK; 826 827 /** 828 * Maximum length of the build-time index-2 array. 829 * Maximum number of Unicode code points (0x110000) shifted right by UTRIE2_SHIFT_2, 830 * plus the part of the index-2 table for lead surrogate code points, 831 * plus the build-time index gap, 832 * plus the null index-2 block. 833 */ 834 static final int UNEWTRIE2_MAX_INDEX_2_LENGTH= 835 (0x110000>>UTRIE2_SHIFT_2)+ 836 UTRIE2_LSCP_INDEX_2_LENGTH+ 837 UNEWTRIE2_INDEX_GAP_LENGTH+ 838 UTRIE2_INDEX_2_BLOCK_LENGTH; 839 840 static final int UNEWTRIE2_INDEX_1_LENGTH = 0x110000>>UTRIE2_SHIFT_1; 841 842 /** 843 * Maximum length of the build-time data array. 844 * One entry per 0x110000 code points, plus the illegal-UTF-8 block and the null block, 845 * plus values for the 0x400 surrogate code units. 846 */ 847 static final int UNEWTRIE2_MAX_DATA_LENGTH = (0x110000+0x40+0x40+0x400); 848 849 850 851 /** 852 * Implementation class for an iterator over a Trie2. 853 * 854 * Iteration over a Trie2 first returns all of the ranges that are indexed by code points, 855 * then returns the special alternate values for the lead surrogates 856 * 857 * @hide draft / provisional / internal are hidden on OHOS 858 */ 859 class Trie2Iterator implements Iterator<Range> { 860 // The normal constructor that configures the iterator to cover the complete 861 // contents of the Trie2 Trie2Iterator(ValueMapper vm)862 Trie2Iterator(ValueMapper vm) { 863 mapper = vm; 864 nextStart = 0; 865 limitCP = 0x110000; 866 doLeadSurrogates = true; 867 } 868 869 // An alternate constructor that configures the iterator to cover only the 870 // code points corresponding to a particular Lead Surrogate value. Trie2Iterator(char leadSurrogate, ValueMapper vm)871 Trie2Iterator(char leadSurrogate, ValueMapper vm) { 872 if (leadSurrogate < 0xd800 || leadSurrogate > 0xdbff) { 873 throw new IllegalArgumentException("Bad lead surrogate value."); 874 } 875 mapper = vm; 876 nextStart = (leadSurrogate - 0xd7c0) << 10; 877 limitCP = nextStart + 0x400; 878 doLeadSurrogates = false; // Do not iterate over lead the special lead surrogate 879 // values after completing iteration over code points. 880 } 881 882 /** 883 * The main next() function for Trie2 iterators 884 * 885 */ 886 @Override next()887 public Range next() { 888 if (!hasNext()) { 889 throw new NoSuchElementException(); 890 } 891 if (nextStart >= limitCP) { 892 // Switch over from iterating normal code point values to 893 // doing the alternate lead-surrogate values. 894 doingCodePoints = false; 895 nextStart = 0xd800; 896 } 897 int endOfRange = 0; 898 int val = 0; 899 int mappedVal = 0; 900 901 if (doingCodePoints) { 902 // Iteration over code point values. 903 val = get(nextStart); 904 mappedVal = mapper.map(val); 905 endOfRange = rangeEnd(nextStart, limitCP, val); 906 // Loop once for each range in the Trie2 with the same raw (unmapped) value. 907 // Loop continues so long as the mapped values are the same. 908 for (;;) { 909 if (endOfRange >= limitCP-1) { 910 break; 911 } 912 val = get(endOfRange+1); 913 if (mapper.map(val) != mappedVal) { 914 break; 915 } 916 endOfRange = rangeEnd(endOfRange+1, limitCP, val); 917 } 918 } else { 919 // Iteration over the alternate lead surrogate values. 920 val = getFromU16SingleLead((char)nextStart); 921 mappedVal = mapper.map(val); 922 endOfRange = rangeEndLS((char)nextStart); 923 // Loop once for each range in the Trie2 with the same raw (unmapped) value. 924 // Loop continues so long as the mapped values are the same. 925 for (;;) { 926 if (endOfRange >= 0xdbff) { 927 break; 928 } 929 val = getFromU16SingleLead((char)(endOfRange+1)); 930 if (mapper.map(val) != mappedVal) { 931 break; 932 } 933 endOfRange = rangeEndLS((char)(endOfRange+1)); 934 } 935 } 936 returnValue.startCodePoint = nextStart; 937 returnValue.endCodePoint = endOfRange; 938 returnValue.value = mappedVal; 939 returnValue.leadSurrogate = !doingCodePoints; 940 nextStart = endOfRange+1; 941 return returnValue; 942 } 943 944 /** 945 * 946 */ 947 @Override hasNext()948 public boolean hasNext() { 949 return doingCodePoints && (doLeadSurrogates || nextStart < limitCP) || nextStart < 0xdc00; 950 } 951 952 @Override remove()953 public void remove() { 954 throw new UnsupportedOperationException(); 955 } 956 957 958 /** 959 * Find the last lead surrogate in a contiguous range with the 960 * same Trie2 value as the input character. 961 * 962 * Use the alternate Lead Surrogate values from the Trie2, 963 * not the code-point values. 964 * 965 * Note: Trie2_16 and Trie2_32 override this implementation with optimized versions, 966 * meaning that the implementation here is only being used with 967 * Trie2Writable. The code here is logically correct with any type 968 * of Trie2, however. 969 * 970 * @param c The character to begin with. 971 * @return The last contiguous character with the same value. 972 */ rangeEndLS(char startingLS)973 private int rangeEndLS(char startingLS) { 974 if (startingLS >= 0xdbff) { 975 return 0xdbff; 976 } 977 978 int c; 979 int val = getFromU16SingleLead(startingLS); 980 for (c = startingLS+1; c <= 0x0dbff; c++) { 981 if (getFromU16SingleLead((char)c) != val) { 982 break; 983 } 984 } 985 return c-1; 986 } 987 988 // 989 // Iteration State Variables 990 // 991 private ValueMapper mapper; 992 private Range returnValue = new Range(); 993 // The starting code point for the next range to be returned. 994 private int nextStart; 995 // The upper limit for the last normal range to be returned. Normally 0x110000, but 996 // may be lower when iterating over the code points for a single lead surrogate. 997 private int limitCP; 998 999 // True while iterating over the the Trie2 values for code points. 1000 // False while iterating over the alternate values for lead surrogates. 1001 private boolean doingCodePoints = true; 1002 1003 // True if the iterator should iterate the special values for lead surrogates in 1004 // addition to the normal values for code points. 1005 private boolean doLeadSurrogates = true; 1006 } 1007 1008 /** 1009 * Find the last character in a contiguous range of characters with the 1010 * same Trie2 value as the input character. 1011 * 1012 * @param c The character to begin with. 1013 * @return The last contiguous character with the same value. 1014 */ rangeEnd(int start, int limitp, int val)1015 int rangeEnd(int start, int limitp, int val) { 1016 int c; 1017 int limit = Math.min(highStart, limitp); 1018 1019 for (c = start+1; c < limit; c++) { 1020 if (get(c) != val) { 1021 break; 1022 } 1023 } 1024 if (c >= highStart) { 1025 c = limitp; 1026 } 1027 return c - 1; 1028 } 1029 1030 1031 // 1032 // Hashing implementation functions. FNV hash. Respected public domain algorithm. 1033 // initHash()1034 private static int initHash() { 1035 return 0x811c9DC5; // unsigned 2166136261 1036 } 1037 hashByte(int h, int b)1038 private static int hashByte(int h, int b) { 1039 h = h * 16777619; 1040 h = h ^ b; 1041 return h; 1042 } 1043 hashUChar32(int h, int c)1044 private static int hashUChar32(int h, int c) { 1045 h = Trie2.hashByte(h, c & 255); 1046 h = Trie2.hashByte(h, (c>>8) & 255); 1047 h = Trie2.hashByte(h, c>>16); 1048 return h; 1049 } 1050 hashInt(int h, int i)1051 private static int hashInt(int h, int i) { 1052 h = Trie2.hashByte(h, i & 255); 1053 h = Trie2.hashByte(h, (i>>8) & 255); 1054 h = Trie2.hashByte(h, (i>>16) & 255); 1055 h = Trie2.hashByte(h, (i>>24) & 255); 1056 return h; 1057 } 1058 1059 } 1060