<commit_before>/*
 * Copyright (c) 2012, <NAME>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * * Redistributions of source code must retain the above copyright notice, this
 *   list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright notice,
 *   this list of conditions and the following disclaimer in the documentation
 *   and/or other materials provided with the distribution.
 *
 * * Neither the name of the copyright holder nor the names of its
 *   contributors may be used to endorse or promote products derived from
 *   this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package org.apache.pdfbox.filter;


import java.io.EOFException;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;

/**
 * CCITT Modified Huffman RLE, Group 3 (T4) and Group 4 (T6) fax compression.
 *
 * @author <a href="mailto:<EMAIL>"><NAME></a>
 * @author <a href="https://github.com/Schmidor"><NAME></a>
 * @author last modified by $Author: haraldk$
 * @version $Id: CCITTFaxDecoderStream.java,v 1.0 23.05.12 15:55 haraldk Exp$
 * 
 * Taken from commit 24c6682236e5a02151359486aa4075ddc5ab1534 of 18.08.2018 from twelvemonkeys/imageio/plugins/tiff/CCITTFaxDecoderStream.java
 * 
 * Initial changes for PDFBox, discussed in PDFBOX-3338:
 * - removed Validate() usages
 * - catch VALUE_EOL in decode1D()
 */
final class CCITTFaxDecoderStream extends FilterInputStream {
    // See TIFF 6.0 Specification, Section 10: "Modified Huffman Compression", page 43.

    private final int columns;
    private final byte[] decodedRow;

    private final boolean optionG32D;
    // Leading zeros for aligning EOL
    private final boolean optionG3Fill;
    private final boolean optionUncompressed;
    private final boolean optionByteAligned;

    private final int type;

    private int decodedLength;
    private int decodedPos;

    private int[] changesReferenceRow;
    private int[] changesCurrentRow;
    private int changesReferenceRowCount;
    private int changesCurrentRowCount;

    private int lastChangingElement = 0;

    /**
     * Creates a CCITTFaxDecoderStream.
     * This constructor may be used for CCITT streams embedded in PDF files,
     * which use EncodedByteAlign.
     *
     * @param stream the compressed CCITT stream.
     * @param columns the number of columns in the stream.
     * @param type the type of stream, must be one of {@code COMPRESSION_CCITT_MODIFIED_HUFFMAN_RLE},
     *             {@code COMPRESSION_CCITT_T4} or {@code COMPRESSION_CCITT_T6}.
     * @param options CCITT T.4 or T.6 options.
     * @param byteAligned enable byte alignment used in PDF files (EncodedByteAlign).
     */
    public CCITTFaxDecoderStream(final InputStream stream, final int columns, final int type,
                                 final long options, final boolean byteAligned) {
        super(stream);

        this.columns = columns;
        this.type = type;

        // We know this is only used for b/w (1 bit)
        decodedRow = new byte[(columns + 7) / 8];
        changesReferenceRow = new int[columns + 2];
        changesCurrentRow = new int[columns + 2];

        switch (type) {
            case TIFFExtension.COMPRESSION_CCITT_MODIFIED_HUFFMAN_RLE:
                optionByteAligned = byteAligned;
                optionG32D = false;
                optionG3Fill = false;
                optionUncompressed = false;
                break;
            case TIFFExtension.COMPRESSION_CCITT_T4:
                optionByteAligned = byteAligned;
                optionG32D = (options & TIFFExtension.GROUP3OPT_2DENCODING) != 0;
                optionG3Fill = (options & TIFFExtension.GROUP3OPT_FILLBITS) != 0;
                optionUncompressed = (options & TIFFExtension.GROUP3OPT_UNCOMPRESSED) != 0;
                break;
            case TIFFExtension.COMPRESSION_CCITT_T6:
                optionByteAligned = byteAligned;
                optionG32D = false;
                optionG3Fill = false;
                optionUncompressed = (options & TIFFExtension.GROUP4OPT_UNCOMPRESSED) != 0;
                break;
            default:
                throw new IllegalArgumentException("Illegal parameter: " + type);
        }

    }

    private void fetch() throws IOException {
        if (decodedPos >= decodedLength) {
            decodedLength = 0;

            try {
                decodeRow();
            }
            catch (EOFException e) {
                // TODO: Rewrite to avoid throw/catch for normal flow...
                if (decodedLength != 0) {
                    throw e;
                }

                // ..otherwise, just let client code try to read past the
                // end of stream
                decodedLength = -1;
            }

            decodedPos = 0;
        }
    }

    private void decode1D() throws IOException {
        int index = 0;
        boolean white = true;
        changesCurrentRowCount = 0;

        do {
            int completeRun;

            if (white) {
                completeRun = decodeRun(whiteRunTree);
            }
            else {
                completeRun = decodeRun(blackRunTree);<commit_msg>PDFBOX-5339: AAIOBE now wrapped in IOException, copying twelvemonkeys commit by <NAME><commit_after>/*
 * Copyright (c) 2012, <NAME>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * * Redistributions of source code must retain the above copyright notice, this
 *   list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright notice,
 *   this list of conditions and the following disclaimer in the documentation
 *   and/or other materials provided with the distribution.
 *
 * * Neither the name of the copyright holder nor the names of its
 *   contributors may be used to endorse or promote products derived from
 *   this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package org.apache.pdfbox.filter;


import java.io.EOFException;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;

/**
 * CCITT Modified Huffman RLE, Group 3 (T4) and Group 4 (T6) fax compression.
 *
 * @author <a href="mailto:<EMAIL>"><NAME></a>
 * @author <a href="https://github.com/Schmidor"><NAME></a>
 * @author last modified by $Author: haraldk$
 * @version $Id: CCITTFaxDecoderStream.java,v 1.0 23.05.12 15:55 haraldk Exp$
 * 
 * Taken from commit 24c6682236e5a02151359486aa4075ddc5ab1534 of 18.08.2018 from twelvemonkeys/imageio/plugins/tiff/CCITTFaxDecoderStream.java
 * 
 * Initial changes for PDFBox, discussed in PDFBOX-3338:
 * - removed Validate() usages
 * - catch VALUE_EOL in decode1D()
 */
final class CCITTFaxDecoderStream extends FilterInputStream {
    // See TIFF 6.0 Specification, Section 10: "Modified Huffman Compression", page 43.

    private final int columns;
    private final byte[] decodedRow;

    private final boolean optionG32D;
    // Leading zeros for aligning EOL
    private final boolean optionG3Fill;
    private final boolean optionUncompressed;
    private final boolean optionByteAligned;

    private final int type;

    private int decodedLength;
    private int decodedPos;

    private int[] changesReferenceRow;
    private int[] changesCurrentRow;
    private int changesReferenceRowCount;
    private int changesCurrentRowCount;

    private int lastChangingElement = 0;

    /**
     * Creates a CCITTFaxDecoderStream.
     * This constructor may be used for CCITT streams embedded in PDF files,
     * which use EncodedByteAlign.
     *
     * @param stream the compressed CCITT stream.
     * @param columns the number of columns in the stream.
     * @param type the type of stream, must be one of {@code COMPRESSION_CCITT_MODIFIED_HUFFMAN_RLE},
     *             {@code COMPRESSION_CCITT_T4} or {@code COMPRESSION_CCITT_T6}.
     * @param options CCITT T.4 or T.6 options.
     * @param byteAligned enable byte alignment used in PDF files (EncodedByteAlign).
     */
    public CCITTFaxDecoderStream(final InputStream stream, final int columns, final int type,
                                 final long options, final boolean byteAligned) {
        super(stream);

        this.columns = columns;
        this.type = type;

        // We know this is only used for b/w (1 bit)
        decodedRow = new byte[(columns + 7) / 8];
        changesReferenceRow = new int[columns + 2];
        changesCurrentRow = new int[columns + 2];

        switch (type) {
            case TIFFExtension.COMPRESSION_CCITT_MODIFIED_HUFFMAN_RLE:
                optionByteAligned = byteAligned;
                optionG32D = false;
                optionG3Fill = false;
                optionUncompressed = false;
                break;
            case TIFFExtension.COMPRESSION_CCITT_T4:
                optionByteAligned = byteAligned;
                optionG32D = (options & TIFFExtension.GROUP3OPT_2DENCODING) != 0;
                optionG3Fill = (options & TIFFExtension.GROUP3OPT_FILLBITS) != 0;
                optionUncompressed = (options & TIFFExtension.GROUP3OPT_UNCOMPRESSED) != 0;
                break;
            case TIFFExtension.COMPRESSION_CCITT_T6:
                optionByteAligned = byteAligned;
                optionG32D = false;
                optionG3Fill = false;
                optionUncompressed = (options & TIFFExtension.GROUP4OPT_UNCOMPRESSED) != 0;
                break;
            default:
                throw new IllegalArgumentException("Illegal parameter: " + type);
        }

    }

    private void fetch() throws IOException {
        if (decodedPos >= decodedLength) {
            decodedLength = 0;

            try {
                decodeRow();
            }
            catch (ArrayIndexOutOfBoundsException e) {
                // Mask the AIOOBE as an IOException
                throw new IOException("Malformed CCITT stream", e);
            }
            catch (EOFException e) {
                // TODO: Rewrite to avoid throw/catch for normal flow...
                if (decodedLength != 0) {
                    throw e;
                }

                // ..otherwise, just let client code try to read past the
                // end of stream
                decodedLength = -1;
            }

            decodedPos = 0;
        }
    }

    private void decode1D() throws IOException {
        int index = 0;
        boolean white = true;
        changesCurrentRowCount = 0;

        do {
            int completeRun;

            if (white) {
                completeRun = decodeRun(whiteRunTree);
            }
            else {
                completeRun = decodeRun(blackRunTree);
{'fraction_non_alphanumeric': 0.07059477487493052, 'fraction_numerical': 0.01762884141983642, 'mean_word_length': 2.469421487603306, 'pattern_counts': {'":': 0, '<': 20, '<?xml version=': 0, '>': 22, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4334556', 'n_tokens_mistral': 3626, 'n_tokens_neox': 3253, 'n_words': 1198}