/*
 * SDK Pullenti Unitext, version 4.33, fabruary 2026. Copyright (c) 2013-2026, Pullenti. All rights reserved. 
 * Non-Commercial Freeware and Commercial Software. 
 * This class is generated using the converter Unisharping (www.unisharping.ru) from Pullenti C# project. 
 * The latest version of the code is available on the site www.pullenti.ru
 */

package com.pullenti.unitext.internal.misc;

public class LzwDecoder {

    public byte[] decode(byte[] data) throws java.io.IOException {
        com.pullenti.unisharp.MemoryStream outputStream = new com.pullenti.unisharp.MemoryStream();
        this._initializeDictionary();
        this.m_Data = data;
        m_BytePointer = 0;
        m_DataBuffer = 0;
        m_NextBits = 0;
        int code;
        int oldCode = 0;
        byte[] str;
        int inits = 0;
        while ((((code = this._getNextCode()))) != 257) {
            if (code == 256) {
                this._initializeDictionary();
                inits++;
                code = this._getNextCode();
                if (code == 257) 
                    break;
                if (code == 256) {
                }
                outputStream.write(m_StringTable.get(code), 0, m_StringTable.get(code).length);
                oldCode = code;
            }
            else if (code < m_TableIndex) {
                str = m_StringTable.get(code);
                outputStream.write(str, 0, str.length);
                this._addEntry(m_StringTable.get(oldCode), str[0]);
                oldCode = code;
            }
            else {
                str = m_StringTable.get(oldCode);
                outputStream.write(str, 0, str.length);
                this._addEntry(str, str[0]);
                outputStream.write(str[0]);
                oldCode = code;
            }
        }
        if (outputStream.length() > (0L)) 
            return outputStream.toByteArray();
        return null;
    }

    private void _initializeDictionary() {
        if (m_StringTable == null) {
            m_StringTable = new java.util.ArrayList<byte[]>();
            for (int i = 0; i < 8192; i++) {
                m_StringTable.add(null);
            }
            for (int i = 0; i < 256; i++) {
                com.pullenti.unisharp.Utils.putArrayValue(m_StringTable, i, new byte[1]);
                m_StringTable.get(i)[0] = (byte)i;
            }
        }
        else 
            for (int i = 256; i < m_StringTable.size(); i++) {
                com.pullenti.unisharp.Utils.putArrayValue(m_StringTable, i, null);
            }
        m_TableIndex = 258;
        m_BitsToGet = 9;
    }

    private void _addEntry(byte[] oldstring, byte newstring) {
        int length = oldstring.length;
        byte[] str = new byte[length + 1];
        for(int iii = 0; iii < (length); iii++) str[(0) + iii] = oldstring[(0) + iii];
        str[length] = newstring;
        com.pullenti.unisharp.Utils.putArrayValue(m_StringTable, m_TableIndex++, str);
        if (m_TableIndex == 511) 
            m_BitsToGet = 10;
        else if (m_TableIndex == 1023) 
            m_BitsToGet = 11;
        else if (m_TableIndex == 2047) 
            m_BitsToGet = 12;
    }

    private int _getNextCode() {
        if (m_BytePointer >= m_Data.length) 
            return 257;
        m_DataBuffer = (m_DataBuffer << 8) | (((Byte.toUnsignedInt(m_Data[m_BytePointer++])) & 0xff));
        m_NextBits += 8;
        if (m_NextBits < m_BitsToGet) {
            if (m_BytePointer >= m_Data.length) 
                return 257;
            m_DataBuffer = (m_DataBuffer << 8) | (((Byte.toUnsignedInt(m_Data[m_BytePointer++])) & 0xff));
            m_NextBits += 8;
        }
        int code = ((m_DataBuffer >> ((m_NextBits - m_BitsToGet)))) & m_AndTable[m_BitsToGet - 9];
        m_NextBits -= m_BitsToGet;
        if (code == 256) {
        }
        return code;
    }

    private int[] m_AndTable = new int[] {511, 1023, 2047, 4095};

    private java.util.ArrayList<byte[]> m_StringTable;

    private byte[] m_Data;

    private int m_TableIndex;

    private int m_BitsToGet = 9;

    private int m_BytePointer;

    private int m_DataBuffer = 0;

    private int m_NextBits = 0;
    public LzwDecoder() {
    }
}
