/*
 * 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.zip;

// Computes Adler32 checksum for a stream of data. An Adler32
// checksum is not as reliable as a CRC32 checksum, but a lot faster to
// compute.
// The specification for Adler32 may be found in RFC 1950.
// ZLIB Compressed Data Format Specification version 3.3)
// From that document:
// "ADLER32 (Adler-32 checksum)
// This contains a checksum value of the uncompressed data
// (excluding any dictionary data) computed according to Adler-32
// algorithm. This algorithm is a 32-bit extension and improvement
// of the Fletcher algorithm, used in the ITU-T X.224 / ISO 8073
// standard.
// Adler-32 is composed of two sums accumulated per byte: s1 is
// the sum of all bytes, s2 is the sum of all s1 values. Both sums
// are done modulo 65521. s1 is initialized to 1, s2 to zero.  The
// Adler-32 checksum is stored as s2*65536 + s1 in most-
// significant-byte first (network) order."
// "8.2. The Adler-32 algorithm
// The Adler-32 algorithm is much faster than the CRC32 algorithm yet
// still provides an extremely low probability of undetected errors.
// The modulo on unsigned long accumulators can be delayed for 5552
// bytes, so the modulo operation time is negligible.  If the bytes
// are a, b, c, the second sum is 3a + 2b + c + 3, and so is position
// and order sensitive, unlike the first sum, which is just a
// checksum.  That 65521 is prime is important to avoid a possible
// large class of two-byte errors that leave the check unchanged.
// (The Fletcher checksum uses 255, which is not prime and which also
// makes the Fletcher check insensitive to single byte changes 0 -
// 255.)
// The sum s1 is initialized to 1 instead of zero to make the length
// of the sequence part of s2, so that the length does not have to be
// checked separately. (Any sequence of zeroes has a Fletcher
// checksum of zero.)"
public class Adler32 implements IChecksum {

    private static final int bASE = (int)65521;

    @Override
    public int getValue() {
        return checksum;
    }


    public Adler32() {
        this.reset();
    }

    @Override
    public void reset() {
        checksum = (int)1;
    }

    @Override
    public void updateByVal(int _value) {
        int s1 = (int)(((int)checksum) & 0xFFFF);
        int s2 = (int)(((int)checksum) >>> 16);
        s1 = (int)(((((int)s1) + ((((int)((int)_value)) & 0xFF)))) % ((int)bASE));
        s2 = (int)(((((int)s1) + ((int)s2))) % ((int)bASE));
        checksum = (int)((((int)s2) << 16) + ((int)s1));
    }

    @Override
    public void updateByBuf(byte[] buffer) {
        try {
            if (buffer == null) 
                throw new IllegalArgumentException("buffer");
            this.updateByBufEx(buffer, 0, buffer.length);
        } catch (Exception ex123) {
        }
    }

    @Override
    public void updateByBufEx(byte[] buffer, int offset, int count) {
        try {
            if (buffer == null) 
                throw new IllegalArgumentException("buffer");
            if (offset < 0) 
                throw new IndexOutOfBoundsException("offset" + " " + "cannot be negative");
            if (count < 0) 
                throw new IndexOutOfBoundsException("count" + " " + "cannot be negative");
            if (offset >= buffer.length) 
                throw new IndexOutOfBoundsException("offset" + " " + "not a valid index into buffer");
            if ((offset + count) > buffer.length) 
                throw new IndexOutOfBoundsException("count" + " " + "exceeds buffer size");
            int s1 = (int)(((int)checksum) & 0xFFFF);
            int s2 = (int)(((int)checksum) >>> 16);
            while (count > 0) {
                int n = 3800;
                if (n > count) 
                    n = count;
                count -= n;
                while ((--n) >= 0) {
                    s1 = (int)(((int)s1) + ((int)((int)(((Byte.toUnsignedInt(buffer[offset++])) & 0xff)))));
                    s2 = (int)(((int)s2) + ((int)s1));
                }
                s1 %= bASE;
                s2 %= bASE;
            }
            checksum = (int)((((int)s2) << 16) | ((int)s1));
        } catch (Exception ex123) {
        }
    }

    private int checksum;

}
