CharsetUTF32.java 8.74 KB
/*
 * Decompiled with CFR 0_118.
 */
package com.adobe.agl.charset;

import com.adobe.agl.charset.*;
import com.adobe.agl.text.UTF16;
import com.adobe.agl.text.UnicodeSet;

import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.IntBuffer;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.CoderResult;

class CharsetUTF32
extends CharsetICU {
    private static final int SIGNATURE_LENGTH = 4;
    private static final byte[] fromUSubstitution_BE = new byte[]{0, 0, -1, -3};
    private static final byte[] fromUSubstitution_LE = new byte[]{-3, -1, 0, 0};
    private static final byte[] BOM_BE = new byte[]{0, 0, -2, -1};
    private static final byte[] BOM_LE = new byte[]{-1, -2, 0, 0};
    private static final int ENDIAN_XOR_BE = 0;
    private static final int ENDIAN_XOR_LE = 3;
    private static final int NEED_TO_WRITE_BOM = 1;
    private boolean isEndianSpecified;
    private boolean isBigEndian;
    private int endianXOR;
    private byte[] bom;
    private byte[] fromUSubstitution;

    public CharsetUTF32(String icuCanonicalName, String javaCanonicalName, String[] aliases) {
        super(icuCanonicalName, javaCanonicalName, aliases);
        this.isEndianSpecified = this instanceof CharsetUTF32BE || this instanceof CharsetUTF32LE;
        boolean bl = this.isBigEndian = !(this instanceof CharsetUTF32LE);
        if (this.isBigEndian) {
            this.bom = BOM_BE;
            this.fromUSubstitution = fromUSubstitution_BE;
            this.endianXOR = 0;
        } else {
            this.bom = BOM_LE;
            this.fromUSubstitution = fromUSubstitution_LE;
            this.endianXOR = 3;
        }
        this.maxBytesPerChar = 4;
        this.minBytesPerChar = 4;
        this.maxCharsPerByte = 1.0f;
    }

    public CharsetDecoder newDecoder() {
        return new CharsetDecoderUTF32(this);
    }

    public CharsetEncoder newEncoder() {
        return new CharsetEncoderUTF32(this);
    }

    void getUnicodeSetImpl(UnicodeSet setFillIn, int which) {
        CharsetUTF32.getNonSurrogateUnicodeSet(setFillIn);
    }

    class CharsetEncoderUTF32
    extends CharsetEncoderICU {
        private final byte[] temp;

        public CharsetEncoderUTF32(CharsetICU cs) {
            super(cs, CharsetUTF32.this.fromUSubstitution);
            this.temp = new byte[4];
            this.fromUnicodeStatus = CharsetUTF32.this.isEndianSpecified ? 0 : 1;
        }

        protected void implReset() {
            super.implReset();
            this.fromUnicodeStatus = CharsetUTF32.this.isEndianSpecified ? 0 : 1;
        }

        protected CoderResult encodeLoop(CharBuffer source, ByteBuffer target, IntBuffer offsets, boolean flush) {
            CoderResult cr;
            if (this.fromUnicodeStatus == 1) {
                if (!target.hasRemaining()) {
                    return CoderResult.OVERFLOW;
                }
                this.fromUnicodeStatus = 0;
                cr = CharsetEncoderUTF32.fromUWriteBytes(this, CharsetUTF32.this.bom, 0, CharsetUTF32.this.bom.length, target, offsets, -1);
                if (cr.isOverflow()) {
                    return cr;
                }
            }
            if (this.fromUChar32 != 0) {
                if (!target.hasRemaining()) {
                    return CoderResult.OVERFLOW;
                }
                cr = this.encodeChar(source, target, offsets, (char)this.fromUChar32);
                if (cr != null) {
                    return cr;
                }
            }
            do {
                if (!source.hasRemaining()) {
                    return CoderResult.UNDERFLOW;
                }
                if (target.hasRemaining()) continue;
                return CoderResult.OVERFLOW;
            } while ((cr = this.encodeChar(source, target, offsets, source.get())) == null);
            return cr;
        }

        private final CoderResult encodeChar(CharBuffer source, ByteBuffer target, IntBuffer offsets, char ch) {
            CoderResult cr;
            int char32;
            int sourceIndex = source.position() - 1;
            if (UTF16.isSurrogate((char)ch)) {
                cr = this.handleSurrogates(source, (char)ch);
                if (cr != null) {
                    return cr;
                }
                char32 = this.fromUChar32;
                this.fromUChar32 = 0;
            } else {
                char32 = ch;
            }
            this.temp[1 ^ CharsetUTF32.access$400((CharsetUTF32)CharsetUTF32.this)] = (byte)(char32 >>> 16);
            this.temp[2 ^ CharsetUTF32.access$400((CharsetUTF32)CharsetUTF32.this)] = (byte)(char32 >>> 8);
            this.temp[3 ^ CharsetUTF32.access$400((CharsetUTF32)CharsetUTF32.this)] = (byte)char32;
            cr = CharsetEncoderUTF32.fromUWriteBytes(this, this.temp, 0, 4, target, offsets, sourceIndex);
            return cr.isUnderflow() ? null : cr;
        }
    }

    class CharsetDecoderUTF32
    extends CharsetDecoderICU {
        private boolean isBOMReadYet;
        private int actualEndianXOR;
        private byte[] actualBOM;

        public CharsetDecoderUTF32(CharsetICU cs) {
            super(cs);
        }

        protected void implReset() {
            super.implReset();
            this.isBOMReadYet = false;
            this.actualBOM = null;
        }

        protected CoderResult decodeLoop(ByteBuffer source, CharBuffer target, IntBuffer offsets, boolean flush) {
            block14 : {
                int char32;
                if (!this.isBOMReadYet) {
                    block13 : {
                        do {
                            if (!source.hasRemaining()) {
                                return CoderResult.UNDERFLOW;
                            }
                            this.toUBytesArray[this.toULength++] = source.get();
                            if (this.toULength == 1) {
                                if ((!CharsetUTF32.this.isEndianSpecified || CharsetUTF32.this.isBigEndian) && this.toUBytesArray[this.toULength - 1] == BOM_BE[this.toULength - 1]) {
                                    this.actualBOM = BOM_BE;
                                    this.actualEndianXOR = 0;
                                    continue;
                                }
                                if (!(CharsetUTF32.this.isEndianSpecified && CharsetUTF32.this.isBigEndian || this.toUBytesArray[this.toULength - 1] != BOM_LE[this.toULength - 1])) {
                                    this.actualBOM = BOM_LE;
                                    this.actualEndianXOR = 3;
                                    continue;
                                }
                                this.actualBOM = null;
                                this.actualEndianXOR = CharsetUTF32.this.endianXOR;
                                break block13;
                            }
                            if (this.toUBytesArray[this.toULength - 1] != this.actualBOM[this.toULength - 1]) {
                                this.actualBOM = null;
                                this.actualEndianXOR = CharsetUTF32.this.endianXOR;
                                break block13;
                            }
                            if (this.toULength == 4) break;
                        } while (true);
                        this.toULength = 0;
                    }
                    this.isBOMReadYet = true;
                }
                do {
                    if (this.toULength < 4) {
                        if (!source.hasRemaining()) {
                            return CoderResult.UNDERFLOW;
                        }
                        this.toUBytesArray[this.toULength++] = source.get();
                        continue;
                    }
                    if (!target.hasRemaining()) {
                        return CoderResult.OVERFLOW;
                    }
                    char32 = 0;
                    for (int i = 0; i < 4; ++i) {
                        char32 = char32 << 8 | this.toUBytesArray[i ^ this.actualEndianXOR] & 255;
                    }
                    if (0 > char32 || char32 > 1114111 || CharsetICU.isSurrogate(char32)) break block14;
                    this.toULength = 0;
                    if (char32 <= 65535) {
                        target.put((char)char32);
                        continue;
                    }
                    target.put(UTF16.getLeadSurrogate(char32));
                    char32 = UTF16.getTrailSurrogate(char32);
                    if (!target.hasRemaining()) break;
                    target.put((char)char32);
                } while (true);
                this.charErrorBufferArray[0] = (char)char32;
                this.charErrorBufferLength = 1;
                return CoderResult.OVERFLOW;
            }
            return CoderResult.malformedForLength(this.toULength);
        }
    }

}