IntTrieBuilder.java 8.2 KB
/*
 * Decompiled with CFR 0_118.
 */
package com.adobe.agl.impl;

import com.adobe.agl.impl.IntTrie;
import com.adobe.agl.impl.Trie;
import com.adobe.agl.impl.TrieBuilder;
import com.adobe.agl.text.UTF16;

import java.util.Arrays;

public class IntTrieBuilder
extends TrieBuilder {
    protected int[] m_data_;
    protected int m_initialValue_;
    private int m_leadUnitValue_;

    public IntTrieBuilder(IntTrieBuilder table) {
        super(table);
        this.m_data_ = new int[this.m_dataCapacity_];
        System.arraycopy(table.m_data_, 0, this.m_data_, 0, this.m_dataLength_);
        this.m_initialValue_ = table.m_initialValue_;
        this.m_leadUnitValue_ = table.m_leadUnitValue_;
    }

    public IntTrieBuilder(int[] aliasdata, int maxdatalength, int initialvalue, int leadunitvalue, boolean latin1linear) {
        if (maxdatalength < 32 || latin1linear && maxdatalength < 1024) {
            throw new IllegalArgumentException("Argument maxdatalength is too small");
        }
        this.m_data_ = aliasdata != null ? aliasdata : new int[maxdatalength];
        int j = 32;
        if (latin1linear) {
            int i = 0;
            do {
                this.m_index_[i++] = j;
                j += 32;
            } while (i < 8);
        }
        this.m_dataLength_ = j;
        Arrays.fill(this.m_data_, 0, this.m_dataLength_, initialvalue);
        this.m_initialValue_ = initialvalue;
        this.m_leadUnitValue_ = leadunitvalue;
        this.m_dataCapacity_ = maxdatalength;
        this.m_isLatin1Linear_ = latin1linear;
        this.m_isCompacted_ = false;
    }

    public int getValue(int ch) {
        if (this.m_isCompacted_ || ch > 1114111 || ch < 0) {
            return 0;
        }
        int block = this.m_index_[ch >> 5];
        return this.m_data_[Math.abs(block) + (ch & 31)];
    }

    public boolean setValue(int ch, int value) {
        if (this.m_isCompacted_ || ch > 1114111 || ch < 0) {
            return false;
        }
        int block = this.getDataBlock(ch);
        if (block < 0) {
            return false;
        }
        this.m_data_[block + (ch & 31)] = value;
        return true;
    }

    public IntTrie serialize(TrieBuilder.DataManipulate datamanipulate, Trie.DataManipulate triedatamanipulate) {
        if (datamanipulate == null) {
            throw new IllegalArgumentException("Parameters can not be null");
        }
        if (!this.m_isCompacted_) {
            this.compact(false);
            this.fold(datamanipulate);
            this.compact(true);
            this.m_isCompacted_ = true;
        }
        if (this.m_dataLength_ >= 262144) {
            throw new ArrayIndexOutOfBoundsException("Data length too small");
        }
        char[] index = new char[this.m_indexLength_];
        int[] data = new int[this.m_dataLength_];
        for (int i = 0; i < this.m_indexLength_; ++i) {
            index[i] = (char)(this.m_index_[i] >>> 2);
        }
        System.arraycopy(this.m_data_, 0, data, 0, this.m_dataLength_);
        int options = 37;
        options |= 256;
        if (this.m_isLatin1Linear_) {
            options |= 512;
        }
        return new IntTrie(index, data, this.m_initialValue_, options, triedatamanipulate);
    }

    private int allocDataBlock() {
        int newBlock = this.m_dataLength_;
        int newTop = newBlock + 32;
        if (newTop > this.m_dataCapacity_) {
            return -1;
        }
        this.m_dataLength_ = newTop;
        return newBlock;
    }

    private int getDataBlock(int ch) {
        int indexValue = this.m_index_[ch >>= 5];
        if (indexValue > 0) {
            return indexValue;
        }
        int newBlock = this.allocDataBlock();
        if (newBlock < 0) {
            return -1;
        }
        this.m_index_[ch] = newBlock;
        System.arraycopy(this.m_data_, Math.abs(indexValue), this.m_data_, newBlock, 128);
        return newBlock;
    }

    private void compact(boolean overlap) {
        int newStart;
        int i;
        if (this.m_isCompacted_) {
            return;
        }
        this.findUnusedBlocks();
        int overlapStart = 32;
        if (this.m_isLatin1Linear_) {
            overlapStart += 256;
        }
        int start = newStart = 32;
        while (start < this.m_dataLength_) {
            if (this.m_map_[start >>> 5] < 0) {
                start += 32;
                continue;
            }
            if (start >= overlapStart && (i = IntTrieBuilder.findSameDataBlock(this.m_data_, newStart, start, overlap ? 4 : 32)) >= 0) {
                this.m_map_[start >>> 5] = i;
                start += 32;
                continue;
            }
            if (overlap && start >= overlapStart) {
                for (i = 28; i > 0 && !IntTrieBuilder.equal_int(this.m_data_, newStart - i, start, i); i -= 4) {
                }
            } else {
                i = 0;
            }
            if (i > 0) {
                this.m_map_[start >>> 5] = newStart - i;
                start += i;
                for (i = 32 - i; i > 0; --i) {
                    this.m_data_[newStart++] = this.m_data_[start++];
                }
                continue;
            }
            if (newStart < start) {
                this.m_map_[start >>> 5] = newStart;
                for (i = 32; i > 0; --i) {
                    this.m_data_[newStart++] = this.m_data_[start++];
                }
                continue;
            }
            this.m_map_[start >>> 5] = start;
            start = newStart += 32;
        }
        for (i = 0; i < this.m_indexLength_; ++i) {
            this.m_index_[i] = this.m_map_[Math.abs(this.m_index_[i]) >>> 5];
        }
        this.m_dataLength_ = newStart;
    }

    private static final int findSameDataBlock(int[] data, int dataLength, int otherBlock, int step) {
        for (int block = 0; block <= (dataLength -= 32); block += step) {
            if (!IntTrieBuilder.equal_int(data, block, otherBlock, 32)) continue;
            return block;
        }
        return -1;
    }

    private final void fold(TrieBuilder.DataManipulate manipulate) {
        int[] leadIndexes = new int[32];
        int[] index = this.m_index_;
        System.arraycopy(index, 1728, leadIndexes, 0, 32);
        int block = 0;
        if (this.m_leadUnitValue_ != this.m_initialValue_) {
            block = this.allocDataBlock();
            if (block < 0) {
                throw new IllegalStateException("Internal error: Out of memory space");
            }
            this.fillBlock(block, 0, 32, this.m_leadUnitValue_, true);
            block = - block;
        }
        for (int c = 1728; c < 1760; ++c) {
            this.m_index_[c] = block;
        }
        int indexLength = 2048;
        int c2 = 65536;
        while (c2 < 1114112) {
            if (index[c2 >> 5] != 0) {
                int value;
                if ((value = manipulate.getFoldedValue(c2 &= -1024, (block = IntTrieBuilder.findSameIndexBlock(index, indexLength, c2 >> 5)) + 32)) != this.getValue(UTF16.getLeadSurrogate(c2))) {
                    if (!this.setValue(UTF16.getLeadSurrogate(c2), value)) {
                        throw new ArrayIndexOutOfBoundsException("Data table overflow");
                    }
                    if (block == indexLength) {
                        System.arraycopy(index, c2 >> 5, index, indexLength, 32);
                        indexLength += 32;
                    }
                }
                c2 += 1024;
                continue;
            }
            c2 += 32;
        }
        if (indexLength >= 34816) {
            throw new ArrayIndexOutOfBoundsException("Index table overflow");
        }
        System.arraycopy(index, 2048, index, 2080, indexLength - 2048);
        System.arraycopy(leadIndexes, 0, index, 2048, 32);
        this.m_indexLength_ = indexLength += 32;
    }

    private void fillBlock(int block, int start, int limit, int value, boolean overwrite) {
        limit += block;
        block += start;
        if (overwrite) {
            while (block < limit) {
                this.m_data_[block++] = value;
            }
        } else {
            while (block < limit) {
                if (this.m_data_[block] == this.m_initialValue_) {
                    this.m_data_[block] = value;
                }
                ++block;
            }
        }
    }
}