FontByteArray.java 9.89 KB
/*
 * Decompiled with CFR 0_118.
 */
package com.adobe.fontengine.font;

import com.adobe.fontengine.font.FontInputStream;
import com.adobe.fontengine.font.InvalidFontException;
import java.io.IOException;
import java.io.OutputStream;

public class FontByteArray {
    private static final int kMaxBufferLength = 204800;
    private static final int kBufferGrowthAmount = 8192;
    private byte[][] data;
    private int size;
    private int used;

    public FontByteArray(int size) {
        this.size = size;
        this.used = 0;
        int numberBuffers = size / 204800 + (size % 204800 == 0 ? 0 : 1);
        this.data = new byte[numberBuffers][];
        for (int buffer = 0; buffer < numberBuffers; ++buffer) {
            int bufferSize = Math.min(204800, size);
            this.data[buffer] = new byte[bufferSize];
            size -= bufferSize;
        }
    }

    public FontByteArray(FontInputStream in, int inStreamSize) throws IOException, InvalidFontException {
        this(inStreamSize);
        this.addBytes(in, inStreamSize, 0);
    }

    protected FontByteArray(FontByteArray original, boolean copyData) {
        this.size = original.size;
        this.used = original.used;
        if (copyData) {
            this.data = new byte[original.data.length][];
            for (int i = 0; i < original.data.length; ++i) {
                this.data[i] = (byte[])original.data[i].clone();
            }
        } else {
            this.data = original.data;
            original.data = null;
        }
    }

    void addBytes(FontInputStream in, int inStreamSize, int offset) throws IOException, InvalidFontException {
        int subOffset = offset % 204800;
        for (int buffer = offset / 204800; buffer < this.data.length; ++buffer) {
            int bytesRead = 0;
            int toRead = Math.min(this.data[buffer].length - subOffset, inStreamSize);
            while (toRead > 0) {
                int n = in.read(this.data[buffer], bytesRead + subOffset, toRead);
                if (n == -1) {
                    throw new InvalidFontException("not enough data");
                }
                toRead -= n;
                bytesRead += n;
                subOffset = 0;
            }
            this.used += bytesRead;
        }
    }

    public final int getSize() {
        return this.used;
    }

    protected final int getRawByte(int index) throws InvalidFontException {
        if (index < 0 || index >= this.size) {
            throw new InvalidFontException("Invalid index = " + index);
        }
        return this.data[index / 204800][index % 204800] & 255;
    }

    protected final int getSignedRawByte(int index) throws InvalidFontException {
        if (index < 0 || index >= this.size) {
            throw new InvalidFontException("Invalid index = " + index);
        }
        return this.data[index / 204800][index % 204800];
    }

    public final void getBytes(FontByteArray toArray, int toBufferOffset, int fromBufferOffset, int fromBufferLength) {
        int bytesToCopy;
        for (int bytesCopied = 0; bytesCopied < fromBufferLength; bytesCopied += bytesToCopy) {
            int fromBuffer = (fromBufferOffset + bytesCopied) / 204800;
            int fromBufferSubOffset = (fromBufferOffset + bytesCopied) % 204800;
            int toBuffer = (toBufferOffset + bytesCopied) / 204800;
            int toBufferSubOffset = (toBufferOffset + bytesCopied) % 204800;
            bytesToCopy = Math.min(fromBufferLength - bytesCopied, this.data[fromBuffer].length - fromBufferSubOffset);
            if (bytesToCopy <= 0) {
                throw new ArrayIndexOutOfBoundsException("Source buffer is too small");
            }
            bytesToCopy = Math.min(bytesToCopy, toArray.data[toBuffer].length - toBufferSubOffset);
            System.arraycopy(this.data[fromBuffer], fromBufferSubOffset, toArray.data[toBuffer], toBufferSubOffset, bytesToCopy);
        }
    }

    public final byte[] getBytes(int index, int length) {
        int bytesToCopy;
        byte[] b = new byte[length];
        for (int bytesCopied = 0; bytesCopied < length; bytesCopied += bytesToCopy) {
            int buffer = (index + bytesCopied) / 204800;
            int offset = (index + bytesCopied) % 204800;
            bytesToCopy = Math.min(length - bytesCopied, this.data[buffer].length - offset);
            System.arraycopy(this.data[buffer], offset, b, bytesCopied, bytesToCopy);
        }
        return b;
    }

    public void write(OutputStream out) throws IOException {
        int buffer = 0;
        int dataWritten = 0;
        while (dataWritten < this.used) {
            int dataToWrite = Math.min(this.used - dataWritten, 204800);
            out.write(this.data[buffer], 0, dataToWrite);
            dataWritten += dataToWrite;
            ++buffer;
        }
    }

    public boolean equals(Object other) {
        if (this == other) {
            return true;
        }
        if (!(other instanceof FontByteArray)) {
            return false;
        }
        FontByteArray otherBA = (FontByteArray)other;
        if (otherBA.used != this.used) {
            return false;
        }
        for (int i = 0; i < this.used; ++i) {
            try {
                if (this.getRawByte(i) == otherBA.getRawByte(i)) continue;
                return false;
            }
            catch (InvalidFontException e) {
                throw new RuntimeException("Unable to get data at index = " + i, e);
            }
        }
        return true;
    }

    public int hashCode() {
        int hashCode = this.used;
        int bytesToCheck = Math.min(this.used, 10);
        for (int i = 0; i < bytesToCheck; ++i) {
            hashCode = hashCode * 31 + this.data[0][1];
        }
        return hashCode;
    }

    static /* synthetic */ int access$212(FontByteArray x0, int x1) {
        return x0.size += x1;
    }

    protected static class FontByteArrayBuilder {
        protected FontByteArray byteArray;

        protected FontByteArrayBuilder(FontByteArray byteArray) {
            this.byteArray = byteArray;
        }

        protected final void setRawByte(int index, int value) {
            this.ensureCapacity(index + 1);
            FontByteArray.access$000((FontByteArray)this.byteArray)[index / 204800][index % 204800] = (byte)(value & 255);
            this.byteArray.used = Math.max(this.byteArray.used, index + 1);
        }

        protected final int getRawByte(int index) {
            return this.byteArray.data[index / 204800][index % 204800];
        }

        protected final void appendRawByte(int value) {
            int index = this.byteArray.used;
            this.ensureCapacity(index + 1);
            this.setRawByte(index, value);
        }

        public int getSize() {
            return this.byteArray.getSize();
        }

        public final void replace(int position, FontByteArray other, int start, int length) throws InvalidFontException {
            this.ensureCapacity(position + length);
            if (length > 0) {
                other.getBytes(this.byteArray, position, start, length);
                this.byteArray.used = Math.max(this.byteArray.used, position + length);
            }
        }

        public final void replace(int position, byte[] b, int start, int length) {
            this.ensureCapacity(position + length);
            for (int i = 0; i < length; ++i) {
                this.setRawByte(position + i, b[i + start]);
            }
        }

        public final void append(FontByteArray other, int start, int length) throws InvalidFontException {
            this.replace(this.byteArray.used, other, start, length);
        }

        public final void append(byte[] b, int start, int length) {
            this.replace(this.byteArray.used, b, start, length);
        }

        public final void append(FontInputStream in, int inStreamSize, int offset) throws IOException, InvalidFontException {
            this.byteArray.addBytes(in, inStreamSize, offset);
        }

        public final void ensureCapacity(int minCapacity) {
            if (minCapacity > this.byteArray.size) {
                this.grow(minCapacity);
            }
        }

        public final void ensureFreeSpace(int minSpace) {
            if (this.byteArray.size - this.byteArray.used < minSpace) {
                this.grow(this.byteArray.used + minSpace);
            }
        }

        private final void grow(int size) {
            int numberBuffers;
            int lastBufferNumber = this.byteArray.data.length - 1;
            if (this.byteArray.data[lastBufferNumber].length != 204800) {
                int growSize = Math.max(size - this.byteArray.size, 8192);
                int newBufferSize = this.byteArray.data[lastBufferNumber].length + growSize;
                newBufferSize = Math.min(newBufferSize, 204800);
                byte[] newBuffer = new byte[newBufferSize];
                FontByteArray.access$212(this.byteArray, newBufferSize - this.byteArray.data[lastBufferNumber].length);
                System.arraycopy(this.byteArray.data[lastBufferNumber], 0, newBuffer, 0, this.byteArray.data[lastBufferNumber].length);
                FontByteArray.access$000((FontByteArray)this.byteArray)[lastBufferNumber] = newBuffer;
            }
            if ((numberBuffers = size / 204800 + (size % 204800 == 0 ? 0 : 1)) != this.byteArray.data.length) {
                byte[][] buffers = new byte[numberBuffers][];
                for (int buffer = 0; buffer < numberBuffers; ++buffer) {
                    if (buffer <= lastBufferNumber) {
                        buffers[buffer] = this.byteArray.data[buffer];
                        size -= buffers[buffer].length;
                        continue;
                    }
                    int bufferSize = Math.min(204800, size);
                    buffers[buffer] = new byte[bufferSize];
                    size -= bufferSize;
                    FontByteArray.access$212(this.byteArray, bufferSize);
                }
                this.byteArray.data = buffers;
            }
        }
    }

}