/* * Copyright 2004 - 2008 Christian Sprajc, Dennis Waldherr. All rights reserved. * * This file is part of PowerFolder. * * PowerFolder is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation. * * PowerFolder is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with PowerFolder. If not, see <http://www.gnu.org/licenses/>. * * $Id$ */ package de.dal33t.powerfolder.util.delta; import de.dal33t.powerfolder.util.RingBuffer; /** * Adler32 implementation which supports rolling over data. * Although there is a java Adler32 implementation (even done in native code), it lacks * the ability to "roll" over data making it much slower when continuous data has to be * processed. * * @author Dennis "Dante" Waldherr * @version $Revision: 4280 $ */ public final class RollingAdler32 implements RollingChecksum { private final static int MOD_ADLER = 65521; private final RingBuffer rbuf; private final int n; /** Adler32 specific */ private int A = 1, B; public RollingAdler32(int n) { rbuf = new RingBuffer(n); this.n = n; } public void update(int nd) { int fb = 0; nd &= 0xff; // This allows update to be called with bytes directly if (rbuf.remaining() == 0) { fb = rbuf.read(); B--; } rbuf.write(nd); A = A + nd - fb; if (A < 0) { A += MOD_ADLER; } else if (A >= MOD_ADLER) { A -= MOD_ADLER; } B = (B + A - n * fb) % MOD_ADLER; if (B < 0) { B += MOD_ADLER; } } public void update(byte[] data) { update(data, 0, data.length); } public void reset() { A = 1; B = 0; rbuf.reset(); } public void update(byte[] data, int ofs, int len) { if (ofs < 0) { throw new IndexOutOfBoundsException("Offset is negative"); } if (len < 0) { throw new IndexOutOfBoundsException("Length is negative"); } if (ofs + len > data.length) { throw new IndexOutOfBoundsException("Offset + length too large!"); } for (; len > 0; len--) { update(data[ofs++]); } } public int getFrameSize() { return n; } public long getValue() { return ((long) B << 16) | A; } }