/* GENERATED SOURCE. DO NOT MODIFY. */ // © 2016 and later: Unicode, Inc. and others. // License & terms of use: http://www.unicode.org/copyright.html#License /* ******************************************************************************* * Copyright (C) 2009, International Business Machines Corporation and * * others. All Rights Reserved. * ******************************************************************************* */ package android.icu.impl; /** * @author aheninger * * A Trie2Writable is a modifiable, or build-time Trie2. * Functions for reading data from the Trie are all from class Trie2. * @hide Only a subset of ICU is exposed in Android * */ public class Trie2Writable extends Trie2 { /** * Create a new, empty, writable Trie2. 32-bit data values are used. * * @param initialValueP the initial value that is set for all code points * @param errorValueP the value for out-of-range code points and illegal UTF-8 */ public Trie2Writable(int initialValueP, int errorValueP) { // This constructor corresponds to utrie2_open() in ICU4C. init(initialValueP, errorValueP); } private void init(int initialValueP, int errorValueP) { this.initialValue = initialValueP; this.errorValue = errorValueP; this.highStart = 0x110000; this.data = new int[UNEWTRIE2_INITIAL_DATA_LENGTH]; this.dataCapacity = UNEWTRIE2_INITIAL_DATA_LENGTH; this.initialValue = initialValueP; this.errorValue = errorValueP; this.highStart = 0x110000; this.firstFreeBlock = 0; /* no free block in the list */ this.isCompacted = false; /* * preallocate and reset * - ASCII * - the bad-UTF-8-data block * - the null data block */ int i, j; for(i=0; i<0x80; ++i) { data[i] = initialValue; } for(; i<0xc0; ++i) { data[i] = errorValue; } for(i=UNEWTRIE2_DATA_NULL_OFFSET; i>UTRIE2_SHIFT_2 ASCII data blocks */ for(i=0, j=0; j<0x80; ++i, j+=UTRIE2_DATA_BLOCK_LENGTH) { index2[i]=j; map[i]=1; } /* reference counts for the bad-UTF-8-data block */ for(; j<0xc0; ++i, j+=UTRIE2_DATA_BLOCK_LENGTH) { map[i]=0; } /* * Reference counts for the null data block: all blocks except for the ASCII blocks. * Plus 1 so that we don't drop this block during compaction. * Plus as many as needed for lead surrogate code points. */ /* i==newTrie->dataNullOffset */ map[i++] = (0x110000>>UTRIE2_SHIFT_2) - (0x80>>UTRIE2_SHIFT_2) + 1 + UTRIE2_LSCP_INDEX_2_LENGTH; j += UTRIE2_DATA_BLOCK_LENGTH; for(; j>UTRIE2_SHIFT_2; i>UTRIE2_SHIFT_2))+ (c>>UTRIE2_SHIFT_2); } else { i2=index1[c>>UTRIE2_SHIFT_1]+ ((c>>UTRIE2_SHIFT_2)&UTRIE2_INDEX_2_MASK); } block=index2[i2]; return (block==dataNullOffset); } private int allocIndex2Block() { int newBlock, newTop; newBlock=index2Length; newTop=newBlock+UTRIE2_INDEX_2_BLOCK_LENGTH; if(newTop > index2.length) { throw new IllegalStateException("Internal error in Trie2 creation."); /* * Should never occur. * Either UTRIE2_MAX_BUILD_TIME_INDEX_LENGTH is incorrect, * or the code writes more values than should be possible. */ } index2Length=newTop; System.arraycopy(index2, index2NullOffset, index2, newBlock, UTRIE2_INDEX_2_BLOCK_LENGTH); return newBlock; } private int getIndex2Block(int c, boolean forLSCP) { int i1, i2; if(c>=0xd800 && c<0xdc00 && forLSCP) { return UTRIE2_LSCP_INDEX_2_OFFSET; } i1=c>>UTRIE2_SHIFT_1; i2=index1[i1]; if(i2==index2NullOffset) { i2=allocIndex2Block(); index1[i1]=i2; } return i2; } private int allocDataBlock(int copyBlock) { int newBlock, newTop; if(firstFreeBlock!=0) { /* get the first free block */ newBlock=firstFreeBlock; firstFreeBlock=-map[newBlock>>UTRIE2_SHIFT_2]; } else { /* get a new block from the high end */ newBlock=dataLength; newTop=newBlock+UTRIE2_DATA_BLOCK_LENGTH; if(newTop>dataCapacity) { /* out of memory in the data array */ int capacity; int[] newData; if(dataCapacity>UTRIE2_SHIFT_2]=0; return newBlock; } /* call when the block's reference counter reaches 0 */ private void releaseDataBlock(int block) { /* put this block at the front of the free-block chain */ map[block>>UTRIE2_SHIFT_2]=-firstFreeBlock; firstFreeBlock=block; } private boolean isWritableBlock(int block) { return (block!=dataNullOffset && 1==map[block>>UTRIE2_SHIFT_2]); } private void setIndex2Entry(int i2, int block) { int oldBlock; ++map[block>>UTRIE2_SHIFT_2]; /* increment first, in case block==oldBlock! */ oldBlock=index2[i2]; if(0 == --map[oldBlock>>UTRIE2_SHIFT_2]) { releaseDataBlock(oldBlock); } index2[i2]=block; } /** * No error checking for illegal arguments. * * @hide draft / provisional / internal are hidden on Android */ private int getDataBlock(int c, boolean forLSCP) { int i2, oldBlock, newBlock; i2=getIndex2Block(c, forLSCP); i2+=(c>>UTRIE2_SHIFT_2)&UTRIE2_INDEX_2_MASK; oldBlock=index2[i2]; if(isWritableBlock(oldBlock)) { return oldBlock; } /* allocate a new data block */ newBlock=allocDataBlock(oldBlock); setIndex2Entry(i2, newBlock); return newBlock; } /** * Set a value for a code point. * * @param c the code point * @param value the value */ public Trie2Writable set(int c, int value) { if (c<0 || c>0x10ffff) { throw new IllegalArgumentException("Invalid code point."); } set(c, true, value); fHash = 0; return this; } private Trie2Writable set(int c, boolean forLSCP, int value) { int block; if (isCompacted) { uncompact(); } block = getDataBlock(c, forLSCP); data[block + (c&UTRIE2_DATA_MASK)] = value; return this; } /* * Uncompact a compacted Trie2Writable. * This is needed if a the WritableTrie2 was compacted in preparation for creating a read-only * Trie2, and then is subsequently altered. * * The structure is a bit awkward - it would be cleaner to leave the original * Trie2 unaltered - but compacting in place was taken directly from the ICU4C code. * * The approach is to create a new (uncompacted) Trie2Writable from this one, then transfer * the guts from the new to the old. */ private void uncompact() { Trie2Writable tempTrie = new Trie2Writable(this); // Members from Trie2Writable this.index1 = tempTrie.index1; this.index2 = tempTrie.index2; this.data = tempTrie.data; this.index2Length = tempTrie.index2Length; this.dataCapacity = tempTrie.dataCapacity; this.isCompacted = tempTrie.isCompacted; // Members From Trie2 this.header = tempTrie.header; this.index = tempTrie.index; this.data16 = tempTrie.data16; this.data32 = tempTrie.data32; this.indexLength = tempTrie.indexLength; this.dataLength = tempTrie.dataLength; this.index2NullOffset = tempTrie.index2NullOffset; this.initialValue = tempTrie.initialValue; this.errorValue = tempTrie.errorValue; this.highStart = tempTrie.highStart; this.highValueIndex = tempTrie.highValueIndex; this.dataNullOffset = tempTrie.dataNullOffset; } private void writeBlock(int block, int value) { int limit=block+UTRIE2_DATA_BLOCK_LENGTH; while(block