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

import com.adobe.agl.impl.ICUBinary;
import com.adobe.agl.impl.ICUBinaryStream;
import com.adobe.agl.impl.ICUData;
import com.adobe.agl.impl.ICUDebug;
import com.adobe.agl.lang.UCharacter;

import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;

public final class UPropertyAliases
implements ICUBinary.Authenticate {
    private NonContiguousEnumToShort enumToName;
    private NameToEnum nameToEnum;
    private NonContiguousEnumToShort enumToValue;
    private ValueMap[] valueMapArray;
    private short[] nameGroupPool;
    private String[] stringPool;
    private static boolean DEBUG = ICUDebug.enabled("pnames");
    private static final byte[] DATA_FORMAT_ID = new byte[]{112, 110, 97, 109};

    public UPropertyAliases() throws IOException {
        InputStream is = ICUData.getRequiredStream("data/icudt40b/pnames.icu");
        BufferedInputStream b = new BufferedInputStream(is, 8192);
        ICUBinary.readHeader(b, DATA_FORMAT_ID, this);
        DataInputStream d = new DataInputStream(b);
        d.mark(256);
        short enumToName_offset = d.readShort();
        short nameToEnum_offset = d.readShort();
        short enumToValue_offset = d.readShort();
        short total_size = d.readShort();
        short valueMap_offset = d.readShort();
        int valueMap_count = d.readShort();
        short nameGroupPool_offset = d.readShort();
        short nameGroupPool_count = d.readShort();
        short stringPool_offset = d.readShort();
        short stringPool_count = d.readShort();
        if (DEBUG) {
            System.out.println("enumToName_offset=" + enumToName_offset + "\n" + "nameToEnum_offset=" + nameToEnum_offset + "\n" + "enumToValue_offset=" + enumToValue_offset + "\n" + "total_size=" + total_size + "\n" + "valueMap_offset=" + valueMap_offset + "\n" + "valueMap_count=" + valueMap_count + "\n" + "nameGroupPool_offset=" + nameGroupPool_offset + "\n" + "nameGroupPool_count=" + nameGroupPool_count + "\n" + "stringPool_offset=" + stringPool_offset + "\n" + "stringPool_count=" + stringPool_count);
        }
        byte[] raw = new byte[total_size];
        d.reset();
        d.readFully(raw);
        d.close();
        Builder builder = new Builder(raw);
        this.stringPool = builder.readStringPool(stringPool_offset, stringPool_count);
        this.nameGroupPool = builder.readNameGroupPool(nameGroupPool_offset, nameGroupPool_count);
        builder.setupValueMap_map(valueMap_offset, (short)valueMap_count);
        builder.seek(enumToName_offset);
        this.enumToName = new NonContiguousEnumToShort(builder);
        builder.nameGroupOffsetToIndex(this.enumToName.offsetArray);
        builder.seek(nameToEnum_offset);
        this.nameToEnum = new NameToEnum(builder);
        builder.seek(enumToValue_offset);
        this.enumToValue = new NonContiguousEnumToShort(builder);
        builder.valueMapOffsetToIndex(this.enumToValue.offsetArray);
        this.valueMapArray = new ValueMap[valueMap_count];
        for (int i = 0; i < valueMap_count; ++i) {
            builder.seek(builder.valueMap_map[i]);
            this.valueMapArray[i] = new ValueMap(builder);
        }
        builder.close();
    }

    public int getPropertyEnum(String propertyAlias) {
        return this.nameToEnum.getEnum(propertyAlias);
    }

    public int getPropertyValueEnum(int property, String valueAlias) {
        ValueMap vm = this.getValueMap(property);
        return vm.nameToEnum.getEnum(valueAlias);
    }

    public static int compare(String stra, String strb) {
        int istra = 0;
        int istrb = 0;
        char cstra = '\u0000';
        char cstrb = '\u0000';
        block6 : do {
            boolean endstrb;
            if (istra < stra.length()) {
                cstra = stra.charAt(istra);
                switch (cstra) {
                    case '\t': 
                    case '\n': 
                    case '\u000b': 
                    case '\f': 
                    case '\r': 
                    case ' ': 
                    case '-': 
                    case '_': {
                        ++istra;
                        continue block6;
                    }
                }
            }
            block7 : while (istrb < strb.length()) {
                cstrb = strb.charAt(istrb);
                switch (cstrb) {
                    case '\t': 
                    case '\n': 
                    case '\u000b': 
                    case '\f': 
                    case '\r': 
                    case ' ': 
                    case '-': 
                    case '_': {
                        ++istrb;
                        continue block7;
                    }
                    default: {
                        break block7;
                    }
                }
            }
            boolean endstra = istra == stra.length();
            boolean bl = endstrb = istrb == strb.length();
            if (endstra) {
                if (endstrb) {
                    return 0;
                }
                cstra = '\u0000';
            } else if (endstrb) {
                cstrb = '\u0000';
            }
            int rc = UCharacter.toLowerCase(cstra) - UCharacter.toLowerCase(cstrb);
            if (rc != 0) {
                return rc;
            }
            ++istra;
            ++istrb;
        } while (true);
    }

    private ValueMap getValueMap(int property) {
        short valueMapIndex = this.enumToValue.getShort(property);
        return this.valueMapArray[valueMapIndex];
    }

    public boolean isDataVersionAcceptable(byte[] version) {
        return version[0] == 1;
    }

    static class Builder
    extends ICUBinaryStream {
        private short[] stringPool_map;
        private short[] valueMap_map;
        private short[] nameGroup_map;

        public Builder(byte[] raw) {
            super(raw);
        }

        public void setupValueMap_map(short offset, short count) {
            this.valueMap_map = new short[count];
            for (int i = 0; i < count; ++i) {
                this.valueMap_map[i] = (short)(offset + i * 6);
            }
        }

        public String[] readStringPool(short offset, short count) throws IOException {
            this.seek(offset);
            String[] stringPool = new String[count + 1];
            this.stringPool_map = new short[count + 1];
            short pos = offset;
            StringBuffer buf = new StringBuffer();
            this.stringPool_map[0] = 0;
            for (int i = 1; i <= count; ++i) {
                char c;
                buf.setLength(0);
                while ((c = (char)this.readUnsignedByte()) != '\u0000') {
                    buf.append(c);
                }
                this.stringPool_map[i] = pos;
                stringPool[i] = buf.toString();
                pos = (short)(pos + (stringPool[i].length() + 1));
            }
            if (DEBUG) {
                System.out.println("read stringPool x " + count + ": " + stringPool[1] + ", " + stringPool[2] + ", " + stringPool[3] + ",...");
            }
            return stringPool;
        }

        public short[] readNameGroupPool(short offset, short count) throws IOException {
            this.seek(offset);
            short pos = offset;
            short[] nameGroupPool = new short[count];
            this.nameGroup_map = new short[count];
            for (int i = 0; i < count; ++i) {
                this.nameGroup_map[i] = pos;
                nameGroupPool[i] = this.stringOffsetToIndex(this.readShort());
                pos = (short)(pos + 2);
            }
            if (DEBUG) {
                System.out.println("read nameGroupPool x " + count + ": " + nameGroupPool[0] + ", " + nameGroupPool[1] + ", " + nameGroupPool[2] + ",...");
            }
            return nameGroupPool;
        }

        private short stringOffsetToIndex(short offset) {
            short probe = offset;
            if (probe < 0) {
                probe = - probe;
            }
            for (int i = 0; i < this.stringPool_map.length; ++i) {
                if (this.stringPool_map[i] != probe) continue;
                return (short)(offset < 0 ? - i : i);
            }
            throw new IllegalStateException("Can't map string pool offset " + offset + " to index");
        }

        private short valueMapOffsetToIndex(short offset) {
            for (short i = 0; i < this.valueMap_map.length; i = (short)(i + 1)) {
                if (this.valueMap_map[i] != offset) continue;
                return i;
            }
            throw new IllegalStateException("Can't map value map offset " + offset + " to index");
        }

        private void valueMapOffsetToIndex(short[] array) {
            for (int i = 0; i < array.length; ++i) {
                array[i] = this.valueMapOffsetToIndex(array[i]);
            }
        }

        private short nameGroupOffsetToIndex(short offset) {
            for (short i = 0; i < this.nameGroup_map.length; i = (short)(i + 1)) {
                if (this.nameGroup_map[i] != offset) continue;
                return i;
            }
            throw new RuntimeException("Can't map name group offset " + offset + " to index");
        }

        private void nameGroupOffsetToIndex(short[] array) {
            for (int i = 0; i < array.length; ++i) {
                array[i] = this.nameGroupOffsetToIndex(array[i]);
            }
        }
    }

    private class NameToEnum {
        int[] enumArray;
        short[] nameArray;

        int getEnum(String nameProbe) {
            for (int i = 0; i < this.nameArray.length; ++i) {
                int c = UPropertyAliases.compare(nameProbe, UPropertyAliases.this.stringPool[this.nameArray[i]]);
                if (c > 0) continue;
                if (c < 0) break;
                return this.enumArray[i];
            }
            throw new IllegalArgumentException("Invalid name: " + nameProbe);
        }

        NameToEnum(Builder b) throws IOException {
            int i;
            int count = b.readInt();
            this.enumArray = new int[count];
            this.nameArray = new short[count];
            for (i = 0; i < count; ++i) {
                this.enumArray[i] = b.readInt();
            }
            for (i = 0; i < count; ++i) {
                this.nameArray[i] = b.stringOffsetToIndex(b.readShort());
            }
        }
    }

    private static class NonContiguousEnumToShort
    implements EnumToShort {
        int[] enumArray;
        short[] offsetArray;

        public short getShort(int enumProbe) {
            for (int i = 0; i < this.enumArray.length; ++i) {
                if (this.enumArray[i] < enumProbe) continue;
                if (this.enumArray[i] > enumProbe) break;
                return this.offsetArray[i];
            }
            throw new IllegalArgumentException("Invalid enum");
        }

        NonContiguousEnumToShort(ICUBinaryStream s) throws IOException {
            int i;
            int count = s.readInt();
            this.enumArray = new int[count];
            this.offsetArray = new short[count];
            for (i = 0; i < count; ++i) {
                this.enumArray[i] = s.readInt();
            }
            for (i = 0; i < count; ++i) {
                this.offsetArray[i] = s.readShort();
            }
        }
    }

    private static class ContiguousEnumToShort
    implements EnumToShort {
        int enumStart;
        int enumLimit;
        short[] offsetArray;

        ContiguousEnumToShort(ICUBinaryStream s) throws IOException {
            this.enumStart = s.readInt();
            this.enumLimit = s.readInt();
            int count = this.enumLimit - this.enumStart;
            this.offsetArray = new short[count];
            for (int i = 0; i < count; ++i) {
                this.offsetArray[i] = s.readShort();
            }
        }
    }

    private static interface EnumToShort {
    }

    private class ValueMap {
        EnumToShort enumToName;
        NameToEnum nameToEnum;

        ValueMap(Builder b) throws IOException {
            short enumToName_offset = b.readShort();
            short ncEnumToName_offset = b.readShort();
            short nameToEnum_offset = b.readShort();
            if (enumToName_offset != 0) {
                b.seek(enumToName_offset);
                ContiguousEnumToShort x = new ContiguousEnumToShort(b);
                b.nameGroupOffsetToIndex(x.offsetArray);
                this.enumToName = x;
            } else {
                b.seek(ncEnumToName_offset);
                NonContiguousEnumToShort x = new NonContiguousEnumToShort(b);
                b.nameGroupOffsetToIndex(x.offsetArray);
                this.enumToName = x;
            }
            b.seek(nameToEnum_offset);
            this.nameToEnum = new NameToEnum(b);
        }
    }

}