FixASCIIControlsReader.java 4 KB
/*
 * Decompiled with CFR 0_118.
 */
package com.adobe.internal.xmp.impl;

import com.adobe.internal.xmp.impl.Utils;
import java.io.IOException;
import java.io.PushbackReader;
import java.io.Reader;

public class FixASCIIControlsReader
extends PushbackReader {
    private static final int STATE_START = 0;
    private static final int STATE_AMP = 1;
    private static final int STATE_HASH = 2;
    private static final int STATE_HEX = 3;
    private static final int STATE_DIG1 = 4;
    private static final int STATE_ERROR = 5;
    private static final int BUFFER_SIZE = 8;
    private int state = 0;
    private int control = 0;
    private int digits = 0;

    public FixASCIIControlsReader(Reader in) {
        super(in, 8);
    }

    public int read(char[] cbuf, int off, int len) throws IOException {
        int readAhead = 0;
        int read = 0;
        int pos = off;
        char[] readAheadBuffer = new char[8];
        boolean available = true;
        while (available && read < len) {
            boolean bl = available = super.read(readAheadBuffer, readAhead, 1) == 1;
            if (available) {
                int c = this.processChar(readAheadBuffer[readAhead]);
                if (this.state == 0) {
                    if (Utils.isControlChar((char)c)) {
                        c = 32;
                    }
                    cbuf[pos++] = c;
                    readAhead = 0;
                    ++read;
                    continue;
                }
                if (this.state == 5) {
                    this.unread(readAheadBuffer, 0, readAhead + 1);
                    readAhead = 0;
                    continue;
                }
                ++readAhead;
                continue;
            }
            if (readAhead <= 0) continue;
            this.unread(readAheadBuffer, 0, readAhead);
            this.state = 5;
            readAhead = 0;
            available = true;
        }
        return read > 0 || available ? read : -1;
    }

    private char processChar(char ch) {
        switch (this.state) {
            case 0: {
                if (ch == '&') {
                    this.state = 1;
                }
                return ch;
            }
            case 1: {
                this.state = ch == '#' ? 2 : 5;
                return ch;
            }
            case 2: {
                if (ch == 'x') {
                    this.control = 0;
                    this.digits = 0;
                    this.state = 3;
                } else if ('0' <= ch && ch <= '9') {
                    this.control = Character.digit(ch, 10);
                    this.digits = 1;
                    this.state = 4;
                } else {
                    this.state = 5;
                }
                return ch;
            }
            case 4: {
                if ('0' <= ch && ch <= '9') {
                    this.control = this.control * 10 + Character.digit(ch, 10);
                    ++this.digits;
                    this.state = this.digits <= 5 ? 4 : 5;
                } else {
                    if (ch == ';' && Utils.isControlChar((char)this.control)) {
                        this.state = 0;
                        return (char)this.control;
                    }
                    this.state = 5;
                }
                return ch;
            }
            case 3: {
                if ('0' <= ch && ch <= '9' || 'a' <= ch && ch <= 'f' || 'A' <= ch && ch <= 'F') {
                    this.control = this.control * 16 + Character.digit(ch, 16);
                    ++this.digits;
                    this.state = this.digits <= 4 ? 3 : 5;
                } else {
                    if (ch == ';' && Utils.isControlChar((char)this.control)) {
                        this.state = 0;
                        return (char)this.control;
                    }
                    this.state = 5;
                }
                return ch;
            }
            case 5: {
                this.state = 0;
                return ch;
            }
        }
        return ch;
    }
}