Files
CypherCore/Source/Framework/IO/Zlib/Adler32.cs
T
Fabian a3dc7b3f48 Ported .Net Core commits:
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).
2017-10-26 17:23:44 +02:00

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);
}
}
}