io.milton.zsync.Rsum Maven / Gradle / Ivy
The newest version!
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/* Rsum.java
Rsum: A simple, "rolling" checksum based on Adler32
Copyright (C) 2011 Tomas Hlavnicka
This file is a part of Jazsync.
Jazsync 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; either version 2 of the License, or (at
your option) any later version.
Jazsync 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 Jazsync; if not, write to the
Free Software Foundation, Inc.,
59 Temple Place, Suite 330,
Boston, MA 02111-1307
USA
*/
package io.milton.zsync;
/**
* Implementation of rolling checksum for zsync purposes
* @author Tomáš Hlavnička
*/
public class Rsum implements RollingChecksum, Cloneable, java.io.Serializable {
private short a;
private short b;
private int oldByte;
private int blockLength;
private byte[] buffer;
/**
* Constructor of rolling checksum
*/
public Rsum(){
a = b = 0;
oldByte = 0;
}
/**
* Return the value of the currently computed checksum.
*
* @return The currently computed checksum.
*/
@Override
public int getValue() {
return ((a & 0xffff) | (b << 16));
}
/**
* Reset the checksum
*/
@Override
public void reset() {
a = b = 0;
oldByte = 0;
}
/**
* Rolling checksum that takes single byte and compute checksum
* of block from file in offset that equals offset of newByte
* minus length of block
*
* @param newByte New byte that will actualize a checksum
*/
@Override
public void roll(byte newByte) {
short oldUnsignedB=unsignedByte(buffer[oldByte]);
a -= oldUnsignedB;
b -= blockLength * oldUnsignedB;
a += unsignedByte(newByte);
b += a;
buffer[oldByte]=newByte;
oldByte++;
if(oldByte==blockLength){
oldByte=0;
}
}
/**
* Update the checksum with an entirely different block, and
* potentially a different block length.
*
* @param buf The byte array that holds the new block.
* @param offset From whence to begin reading.
* @param length The length of the block to read.
*/
@Override
public void check(byte[] buf, int offset, int length) {
reset();
int index=offset;
short unsignedB;
for(int i=length;i>0;i--){
unsignedB=unsignedByte(buf[index]);
a+=unsignedB;
b+=i*unsignedB;
index++;
}
}
/**
* Update the checksum with an entirely different block, and
* potentially a different block length. This method is only used to
* initialize rolling checksum.
*
* @param buf The byte array that holds the new block.
* @param offset From whence to begin reading.
* @param length The length of the block to read.
*/
@Override
public void first(byte[] buf, int offset, int length) {
reset();
int index=offset;
short unsignedB;
for(int i=length;i>0;i--){
unsignedB=unsignedByte(buf[index]);
a+=unsignedB;
b+=i*unsignedB;
index++;
}
blockLength=length;
buffer = new byte[blockLength];
System.arraycopy(buf, 0, buffer, 0, length);
}
/**
* Returns "unsigned" value of byte
*
* @param b Byte to convert
* @return Unsigned value of byte b
*/
private short unsignedByte(byte b){
if(b<0) {
return (short)(b+256);
}
return b;
}
@Override
public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException cnse) {
throw new Error();
}
}
@Override
public boolean equals(Object o) {
return ((Rsum) o).a == a && ((Rsum) o).b == b;
}
}