a3dc7b3f48
hondacrx: - Initial commit: Switch to .Net Core 2.0 - Fix build and removed not needed files Fabi: - Updated solution platforms. - Changed folder structure. - Change library target framework to netstandard2.0. - Updated solution platforms again... - Removed windows specific kernel32 function usage (Ctrl-C handler).
168 lines
4.8 KiB
C#
168 lines
4.8 KiB
C#
// adler32.cs -- compute the Adler-32 checksum of a data stream
|
|
// Copyright (C) 1995-2007 Mark Adler
|
|
// Copyright (C) 2007-2011 by the Authors
|
|
// For conditions of distribution and use, see copyright notice in License.txt
|
|
|
|
|
|
namespace Framework.IO
|
|
{
|
|
public static partial class ZLib
|
|
{
|
|
private const uint BASE=65521; // largest prime smaller than 65536
|
|
private const uint NMAX=5552; // NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1
|
|
|
|
// =========================================================================
|
|
|
|
// Update a running Adler-32 checksum with the bytes buf[0..len-1] and return the updated checksum.
|
|
// If buf is NULL, this function returns the required initial value for the checksum.
|
|
// An Adler-32 checksum is almost as reliable as a CRC32 but can be computed much faster.
|
|
//
|
|
// Usage example:
|
|
// uint adler=adler32(0, null, 0);
|
|
// while(read_buffer(buffer, length)!=EOF)
|
|
// {
|
|
// adler=adler32(adler, buffer, length);
|
|
// }
|
|
// if(adler!=original_adler) error();
|
|
|
|
public static uint adler32(uint adler, byte[] buf, uint len)
|
|
{
|
|
return adler32(adler, buf, 0, len);
|
|
}
|
|
|
|
public static uint adler32(uint adler, byte[] buf, uint ind, uint len)
|
|
{
|
|
// initial Adler-32 value (deferred check for len==1 speed)
|
|
if(buf==null) return 1;
|
|
|
|
// split Adler-32 into component sums
|
|
uint sum2=(adler>>16)&0xffff;
|
|
adler&=0xffff;
|
|
|
|
//uint ind=0; // index in buf
|
|
|
|
// in case user likes doing a byte at a time, keep it fast
|
|
if(len==1)
|
|
{
|
|
adler+=buf[ind];
|
|
if(adler>=BASE) adler-=BASE;
|
|
sum2+=adler;
|
|
if(sum2>=BASE) sum2-=BASE;
|
|
return adler|(sum2<<16);
|
|
}
|
|
|
|
// in case short lengths are provided, keep it somewhat fast
|
|
if(len<16)
|
|
{
|
|
while(len--!=0)
|
|
{
|
|
adler+=buf[ind++];
|
|
sum2+=adler;
|
|
}
|
|
if(adler>=BASE) adler-=BASE;
|
|
sum2%=BASE; // only added so many BASE's
|
|
return adler|(sum2<<16);
|
|
}
|
|
|
|
// do length NMAX blocks -- requires just one modulo operation
|
|
while(len>=NMAX)
|
|
{
|
|
len-=NMAX;
|
|
uint n=NMAX/16; // NMAX is divisible by 16
|
|
do
|
|
{
|
|
// 16 sums unrolled
|
|
adler+=buf[ind++]; sum2+=adler;
|
|
adler+=buf[ind++]; sum2+=adler;
|
|
adler+=buf[ind++]; sum2+=adler;
|
|
adler+=buf[ind++]; sum2+=adler;
|
|
adler+=buf[ind++]; sum2+=adler;
|
|
adler+=buf[ind++]; sum2+=adler;
|
|
adler+=buf[ind++]; sum2+=adler;
|
|
adler+=buf[ind++]; sum2+=adler;
|
|
adler+=buf[ind++]; sum2+=adler;
|
|
adler+=buf[ind++]; sum2+=adler;
|
|
adler+=buf[ind++]; sum2+=adler;
|
|
adler+=buf[ind++]; sum2+=adler;
|
|
adler+=buf[ind++]; sum2+=adler;
|
|
adler+=buf[ind++]; sum2+=adler;
|
|
adler+=buf[ind++]; sum2+=adler;
|
|
adler+=buf[ind++]; sum2+=adler;
|
|
} while(--n!=0);
|
|
|
|
adler%=BASE;
|
|
sum2%=BASE;
|
|
}
|
|
|
|
// do remaining bytes (less than NMAX, still just one modulo)
|
|
if(len!=0)
|
|
{ // avoid modulos if none remaining
|
|
while(len>=16)
|
|
{
|
|
len-=16;
|
|
adler+=buf[ind++]; sum2+=adler;
|
|
adler+=buf[ind++]; sum2+=adler;
|
|
adler+=buf[ind++]; sum2+=adler;
|
|
adler+=buf[ind++]; sum2+=adler;
|
|
adler+=buf[ind++]; sum2+=adler;
|
|
adler+=buf[ind++]; sum2+=adler;
|
|
adler+=buf[ind++]; sum2+=adler;
|
|
adler+=buf[ind++]; sum2+=adler;
|
|
adler+=buf[ind++]; sum2+=adler;
|
|
adler+=buf[ind++]; sum2+=adler;
|
|
adler+=buf[ind++]; sum2+=adler;
|
|
adler+=buf[ind++]; sum2+=adler;
|
|
adler+=buf[ind++]; sum2+=adler;
|
|
adler+=buf[ind++]; sum2+=adler;
|
|
adler+=buf[ind++]; sum2+=adler;
|
|
adler+=buf[ind++]; sum2+=adler;
|
|
}
|
|
|
|
while(len--!=0)
|
|
{
|
|
adler+=buf[ind++];
|
|
sum2+=adler;
|
|
}
|
|
|
|
adler%=BASE;
|
|
sum2%=BASE;
|
|
}
|
|
|
|
// return recombined sums
|
|
return adler|(sum2<<16);
|
|
}
|
|
|
|
// =========================================================================
|
|
|
|
// Combine two Adler-32 checksums into one. For two sequences of bytes, seq1
|
|
// and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for
|
|
// each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of
|
|
// seq1 and seq2 concatenated, requiring only adler1, adler2, and len2.
|
|
|
|
public static uint adler32_combine_(uint adler1, uint adler2, uint len2)
|
|
{ // the derivation of this formula is left as an exercise for the reader
|
|
uint rem=len2%BASE;
|
|
uint sum1=adler1&0xffff;
|
|
uint sum2=(rem*sum1)%BASE;
|
|
sum1+=(adler2&0xffff)+BASE-1;
|
|
sum2+=((adler1>>16)&0xffff)+((adler2>>16)&0xffff)+BASE-rem;
|
|
if(sum1>=BASE) sum1-=BASE;
|
|
if(sum1>=BASE) sum1-=BASE;
|
|
if(sum2>=(BASE<<1)) sum2-=(BASE<<1);
|
|
if(sum2>=BASE) sum2-=BASE;
|
|
return sum1|(sum2<<16);
|
|
}
|
|
|
|
// =========================================================================
|
|
public static uint adler32_combine(uint adler1, uint adler2, uint len2)
|
|
{
|
|
return adler32_combine_(adler1, adler2, len2);
|
|
}
|
|
|
|
public static uint adler32_combine64(uint adler1, uint adler2, uint len2)
|
|
{
|
|
return adler32_combine_(adler1, adler2, len2);
|
|
}
|
|
}
|
|
}
|