Пример #1
0
        /// <summary>
        /// Fold the normalization data for supplementary code points into a compact
        /// area on top of the BMP-part of the trie index, with the lead surrogates
        /// indexing this compact area.
        /// Duplicate the index values for lead surrogates: From inside the BMP area,
        /// where some may be overridden with folded values, to just after the BMP
        /// area, where they can be retrieved for code point lookups.
        /// </summary>
        ///
        /// <param name="manipulate">fold implementation</param>
        private void Fold(TrieBuilder.DataManipulate manipulate)
        {
            int[] leadIndexes = new int[IBM.ICU.Impl.TrieBuilder.SURROGATE_BLOCK_COUNT_];
            int[] index       = m_index_;
            // copy the lead surrogate indexes into a temporary array
            System.Array.Copy((Array)(index), 0xd800 >> IBM.ICU.Impl.TrieBuilder.SHIFT_, (Array)(leadIndexes), 0, IBM.ICU.Impl.TrieBuilder.SURROGATE_BLOCK_COUNT_);

            // set all values for lead surrogate code *units* to leadUnitValue
            // so that by default runtime lookups will find no data for associated
            // supplementary code points, unless there is data for such code points
            // which will result in a non-zero folding value below that is set for
            // the respective lead units
            // the above saved the indexes for surrogate code *points*
            // fill the indexes with simplified code from utrie_setRange32()
            int block = 0;

            if (m_leadUnitValue_ == m_initialValue_)
            {
                // leadUnitValue == initialValue, use all-initial-value block
                // block = 0; if block here left empty
            }
            else
            {
                // create and fill the repeatBlock
                block = AllocDataBlock();
                if (block < 0)
                {
                    // data table overflow
                    throw new InvalidOperationException(
                              "Internal error: Out of memory space");
                }
                FillBlock(block, 0, IBM.ICU.Impl.TrieBuilder.DATA_BLOCK_LENGTH, m_leadUnitValue_, true);
                // negative block number to indicate that it is a repeat block
                block = -block;
            }
            for (int c = (0xd800 >> IBM.ICU.Impl.TrieBuilder.SHIFT_); c < (0xdc00 >> IBM.ICU.Impl.TrieBuilder.SHIFT_); ++c)
            {
                m_index_[c] = block;
            }

            // Fold significant index values into the area just after the BMP
            // indexes.
            // In case the first lead surrogate has significant data,
            // its index block must be used first (in which case the folding is a
            // no-op).
            // Later all folded index blocks are moved up one to insert the copied
            // lead surrogate indexes.
            int indexLength = IBM.ICU.Impl.TrieBuilder.BMP_INDEX_LENGTH_;

            // search for any index (stage 1) entries for supplementary code points
            for (int c_0 = 0x10000; c_0 < 0x110000;)
            {
                if (index[c_0 >> IBM.ICU.Impl.TrieBuilder.SHIFT_] != 0)
                {
                    // there is data, treat the full block for a lead surrogate
                    c_0 &= ~0x3ff;
                    // is there an identical index block?
                    block = IBM.ICU.Impl.TrieBuilder.FindSameIndexBlock(index, indexLength, c_0 >> IBM.ICU.Impl.TrieBuilder.SHIFT_);

                    // get a folded value for [c..c+0x400[ and,
                    // if different from the value for the lead surrogate code
                    // point, set it for the lead surrogate code unit

                    int value_ren = manipulate.GetFoldedValue(c_0, block
                                                              + IBM.ICU.Impl.TrieBuilder.SURROGATE_BLOCK_COUNT_);
                    if (value_ren != GetValue(IBM.ICU.Text.UTF16.GetLeadSurrogate(c_0)))
                    {
                        if (!SetValue(IBM.ICU.Text.UTF16.GetLeadSurrogate(c_0), value_ren))
                        {
                            // data table overflow
                            throw new IndexOutOfRangeException("Data table overflow".ToString());
                        }
                        // if we did not find an identical index block...
                        if (block == indexLength)
                        {
                            // move the actual index (stage 1) entries from the
                            // supplementary position to the new one
                            System.Array.Copy((Array)(index), c_0 >> IBM.ICU.Impl.TrieBuilder.SHIFT_, (Array)(index), indexLength, IBM.ICU.Impl.TrieBuilder.SURROGATE_BLOCK_COUNT_);
                            indexLength += IBM.ICU.Impl.TrieBuilder.SURROGATE_BLOCK_COUNT_;
                        }
                    }
                    c_0 += 0x400;
                }
                else
                {
                    c_0 += IBM.ICU.Impl.TrieBuilder.DATA_BLOCK_LENGTH;
                }
            }

            // index array overflow?
            // This is to guarantee that a folding offset is of the form
            // UTRIE_BMP_INDEX_LENGTH+n*UTRIE_SURROGATE_BLOCK_COUNT with n=0..1023.
            // If the index is too large, then n>=1024 and more than 10 bits are
            // necessary.
            // In fact, it can only ever become n==1024 with completely unfoldable
            // data and the additional block of duplicated values for lead
            // surrogates.
            if (indexLength >= IBM.ICU.Impl.TrieBuilder.MAX_INDEX_LENGTH_)
            {
                throw new IndexOutOfRangeException("Index table overflow".ToString());
            }
            // make space for the lead surrogate index block and insert it between
            // the BMP indexes and the folded ones
            System.Array.Copy((Array)(index), IBM.ICU.Impl.TrieBuilder.BMP_INDEX_LENGTH_, (Array)(index), IBM.ICU.Impl.TrieBuilder.BMP_INDEX_LENGTH_
                              + IBM.ICU.Impl.TrieBuilder.SURROGATE_BLOCK_COUNT_, indexLength - IBM.ICU.Impl.TrieBuilder.BMP_INDEX_LENGTH_);
            System.Array.Copy((Array)(leadIndexes), 0, (Array)(index), IBM.ICU.Impl.TrieBuilder.BMP_INDEX_LENGTH_, IBM.ICU.Impl.TrieBuilder.SURROGATE_BLOCK_COUNT_);
            indexLength   += IBM.ICU.Impl.TrieBuilder.SURROGATE_BLOCK_COUNT_;
            m_indexLength_ = indexLength;
        }